最近,我發現在我的3D應用程序使用DirectX 9的錯誤是,每次我使用Alt-Tab或CTRL-ALT-刪除程序凍結或似乎做什麼的錯誤。我環顧四周,發現我需要通過使用IDirect3DDevice9::TestCooperativeLevel
和IDirect3DDevice9::Reset
來重置我的設備。但是,我掙扎的時刻是,(據我所知)之前,我Reset
設備,我需要釋放的種源在D3DPOOL_MANAGE
之前,我重置設備和復位後重新分配資源回嗎?我該怎麼做呢?以下是我用於重置設備的代碼(位於IsDeviceLost()
函數中)。如何重置我的DirectX 9設備?
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);
};
Direct.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;
}
}
任何幫助或建議將不勝感激。由於
'D3DPOOL_MANAGED'實際上並不需要這麼多的解決這個問題。最簡單的方法就是創建一些即將失效的事物,以便在發生這種情況時它們已經被銷燬並重新創建。 – chris