VertexBuffer not reloading when using alt-tab

Started by
1 comment, last by jollyjeffers 18 years, 8 months ago
Well for starters I'm working on a engine of sorts. I'm using c++ and directx 9 (June 2005). The program is running in full screen and is supposed to display a texture in 3D space (working on getting billboards to work). It works for the most part in that I can see the polygon just fine when I first run it. However, when I alt-tab out and back in the polygon is not there. It doesn't give me an error and just keeps on running. I figured it was something to do with reseting the camera, or the directx initialzation, but I haven't found anything yet. Here is the code: Mostly just the directx initialization stuff.

#include "Global.h"

DirectXGraphics::DirectXGraphics() {
	d3D_		= NULL;
	device_		= NULL;
	hwnd_		= NULL;
	hInst_		= NULL;
}

HRESULT
DirectXGraphics::InitGraphics(HWND hwnd, HINSTANCE hInst) {
	HRESULT hr;
	D3DXMATRIX matProjection;
	D3DFORMAT format;
	D3DDISPLAYMODE d3ddm;
	float aspect;
	int width, height;

	if((d3D_ = Direct3DCreate9(D3D_SDK_VERSION)) == NULL)
		return FALSE;

	hwnd_ = hwnd;
	hInst_ = hInst;

	if(hwnd_ == NULL)
		return FALSE;
	if (hInst_ == NULL)
		return FALSE;

	if(FAILED(hr = d3D_->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm)))
		return hr;

	width = d3ddm.Width;
	height = d3ddm.Height;

	ZeroMemory(&d3dpp_, sizeof(D3DPRESENT_PARAMETERS));

	d3dpp_.Windowed   = FALSE;
	d3dpp_.SwapEffect = D3DSWAPEFFECT_FLIP;
	d3dpp_.BackBufferWidth  = width;
	d3dpp_.BackBufferHeight = height;
	d3dpp_.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
	d3dpp_.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;

	format = D3DFMT_X8R8G8B8;

	d3dpp_.BackBufferFormat = format;
	d3dpp_.EnableAutoDepthStencil = TRUE;
	d3dpp_.AutoDepthStencilFormat = D3DFMT_D16;
	if(FAILED(hr = d3D_->CreateDevice(D3DADAPTER_DEFAULT, 
			D3DDEVTYPE_HAL, hwnd_, D3DCREATE_SOFTWARE_VERTEXPROCESSING,
			&d3dpp_, &device_))) {
		return hr;
	}

	if(FAILED(hr = device_->SetRenderState(D3DRS_LIGHTING, FALSE)))
		return hr;

	if(FAILED(hr = device_->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE)))
		return hr;
	device_->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
	device_->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);

	if(FAILED(hr = device_->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE)))
		return hr;

	if(FAILED(hr = device_->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE)))
		return hr;

	device_->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_COLORVALUE(1.0, 1.0, 1.0, 1.0));

	device_->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
	device_->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
	device_->SetTextureStageState(0, D3DTSS_COLOROP,   D3DTOP_MODULATE);

	device_->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_SELECTARG1);
	device_->SetTextureStageState(0,D3DTSS_COLORARG1,D3DTA_TEXTURE);
	device_->SetTextureStageState(0,D3DTSS_COLORARG2,D3DTA_DIFFUSE);


	device_->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
	device_->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);

	aspect = (float)width / (float)height;

	D3DXMatrixPerspectiveFovLH(&matProjection, D3DX_PI/4, aspect, 1.0f, 10000.0f);
	if(FAILED(hr = device_->SetTransform(D3DTS_PROJECTION, &matProjection)))
		return hr;

	return S_OK;
}

DirectXGraphics::~DirectXGraphics() {
	Shutdown();
}

HRESULT 
DirectXGraphics::BeginScene() {
	HRESULT hr;
	hr = device_->BeginScene();
	return hr;
}

HRESULT 
DirectXGraphics::EndScene() {
	HRESULT hr;
	hr = device_->EndScene();
	return hr;
}

HRESULT 
DirectXGraphics::Display() {
	HRESULT hr;
	hr = device_->Present(NULL,NULL,NULL,NULL);
	return hr;
}

HRESULT 
DirectXGraphics::Clear() {
	HRESULT hr;
	hr = device_->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00FF0000, 1.0f, 0);
	return hr;
}

HRESULT 
DirectXGraphics::Shutdown() {
	hwnd_ = NULL;
	hInst_ = NULL;
	ReleaseCOM(d3D_);
	ReleaseCOM(device_);
	return S_OK;
}

HRESULT
DirectXGraphics::FreeDevice() {
	Sleep(500);
	return S_OK;
}

HRESULT
DirectXGraphics::InitDevice() {
	HRESULT hr;
	hr = device_->Reset(&d3dpp_);
	return hr;
}

LPDIRECT3DDEVICE9 
DirectXGraphics::GetDevice() {
	return device_;
}

LPDIRECT3D9 
DirectXGraphics::GetD3D() {
	return d3D_;
}

HRESULT
DirectXGraphics::SetWorldPosition(WorldPosition *wp) {
	HRESULT hr;
	if (wp == NULL)
		return E_FAIL;
	hr = device_->SetTransform(D3DTS_WORLD, wp->GetMatrix(device_));
	return hr;
}

HRESULT
DirectXGraphics::SetCamera(Camera *camera) {
	if(device_ == NULL || camera == NULL)
		return E_FAIL;
	return device_->SetTransform(D3DTS_VIEW, camera->GetMatrix());
}

The game loop

#include "Global.h"

Engine::Engine() {
	hInst_ = NULL;
	hwnd_ = NULL;
	graphics_ = new DirectXGraphics();
	font_ = new Font();
	frameRate_ = new FrameRate();
	worldPos_ = new WorldPosition();
	billboard_ = new Billboard();
	camera_ = new Camera();
}

Engine::~Engine() {
	Shutdown();
}

HRESULT
Engine::Init(HWND hwnd, HINSTANCE hInst) {
	hwnd_ = hwnd;
	hInst_ = hInst;
	if (hwnd_ == NULL)
		return E_FAIL;
	if (hInst_ == NULL)
		return E_FAIL;
	if (FAILED(graphics_->InitGraphics(hwnd_, hInst_)))
		return E_FAIL;
	if (FAILED(font_->Create(graphics_->GetDevice())))
		return E_FAIL;
	if (FAILED(graphics_->SetWorldPosition(worldPos_)))
		return E_FAIL;
	camera_->Move(0.0f,0.0f, -10.0f);
	camera_->Update();
	if (FAILED(graphics_->SetCamera(camera_)))
		return E_FAIL;
	if (FAILED(billboard_->SetupBitmap("texture.bmp",1.0f,1.0f,1.0f,1.0f,
			graphics_->GetDevice())))
		return E_FAIL;
	return S_OK;
}

HRESULT
Engine::Frame() {
	frameRate_->Update();
	if (GetAsyncKeyState(VK_ESCAPE))
		PostQuitMessage(0);
	if (SUCCEEDED(LostDevice()))
		if (FAILED(Render()))
			PostQuitMessage(0);
	return S_OK;
}

HRESULT
Engine::Render() {
	int num;
	char stuff[256];
	char* rate = frameRate_->ToString();
	HRESULT hr;
	if (FAILED(hr = graphics_->Clear()))
		return hr;
	if (SUCCEEDED(hr = graphics_->BeginScene())) {
		font_->Render(rate, 12,12);

		billboard_->worldPos_->Move(0.0,2.0,5.0);
		billboard_->worldPos_->Update();
		if (FAILED(billboard_->Render()))
			return E_FAIL;
		graphics_->EndScene();
		hr = graphics_->Display();
	}
	return hr;
}

HRESULT
Engine::LostDevice() {
	HRESULT hr;
	hr = graphics_->GetDevice()->TestCooperativeLevel();
	if (hr == D3DERR_DEVICELOST) {
		font_->FreeDevice();
		billboard_->FreeDevice();
		graphics_->FreeDevice();
		return D3DERR_DEVICELOST;
	} else if (hr == D3DERR_DEVICENOTRESET) {
		if (FAILED(graphics_->InitDevice()))
			PostQuitMessage(0);
		billboard_->InitDevice();
		font_->InitDevice();
	}
	return S_OK;
}

HRESULT
Engine::Shutdown() {
	delete graphics_;
	graphics_ = NULL;
	delete font_;
	font_ = NULL;
	delete frameRate_;
	frameRate_ = NULL;
	delete worldPos_;
	worldPos_ = NULL;
	return S_OK;
}

The billboard where all of the vertexBuffer stuff is. At the moment I commented out the SetTexture just to see if it was something with the CreateVertexBuffer function.

#include "Global.h"

Billboard::Billboard() {
	worldPos_ = new WorldPosition();
	texture_ = NULL;
	device_ = NULL;
	vertexBuffer_ = NULL;
	ptr_ = NULL;
}

Billboard::~Billboard() {
	ReleaseCOM(texture_);
	ReleaseCOM(device_);
	ReleaseCOM(vertexBuffer_);
	delete worldPos_;
	delete ptr_;

}

HRESULT
Billboard::SetupBitmap(char* filename, float w, float h, float u, float v, IDirect3DDevice9 *device) {
	device_ = device;
	if (device_ == NULL)
		return E_FAIL;
	
	strcpy(filename_, filename);

	w = w / 2;
	h = h / 2;

	vertex_[0].x = -w;
	vertex_[0].y = h;
	vertex_[0].z = 0.0f;
	vertex_[0].u = 0.0f;
	vertex_[0].v = 0.0f;

	vertex_[1].x = w;
	vertex_[1].y = h;
	vertex_[1].z = 0.0f;
	vertex_[1].u = u;
	vertex_[1].v = 0.0f;

	vertex_[2].x = -w;
	vertex_[2].y = -h;
	vertex_[2].z = 0.0f;
	vertex_[2].u = 0.0f;
	vertex_[2].v = v;

	vertex_[3].x = w;
	vertex_[3].y = -h;
	vertex_[3].z = 0.0f;
	vertex_[3].u = u;
	vertex_[3].v = v;

	if (FAILED(InitDevice()))
		return E_FAIL;

	return S_OK;
}

HRESULT
Billboard::FreeDevice() {
	ReleaseCOM(vertexBuffer_);
	ReleaseCOM(texture_);
	return S_OK;
}

HRESULT
Billboard::InitDevice() {
	HRESULT hr;
	if(FAILED(hr = device_->CreateVertexBuffer(sizeof(vertex_), 
			D3DUSAGE_WRITEONLY, FVF3D, D3DPOOL_MANAGED, &vertexBuffer_, NULL)))
	return hr;

	if(FAILED(hr = vertexBuffer_->Lock(0, 0, (void**)&ptr_, 0)))
		return hr;
	memcpy(ptr_, vertex_, sizeof(vertex_));
	vertexBuffer_->Unlock();

	if (FAILED(hr = D3DXCreateTextureFromFileEx(device_, filename_, 
			D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_A8R8G8B8, 
			D3DPOOL_MANAGED, D3DX_FILTER_TRIANGLE, D3DX_FILTER_TRIANGLE,
			D3DCOLOR_RGBA(0,0,0,255), NULL, NULL, &texture_)))
		return hr;
	worldPos_->Update();
	return S_OK;
}

HRESULT
Billboard::Render() {
	device_->SetFVF(FVF3D);
//	device_->SetTexture(0, texture_);
	device_->SetTransform(D3DTS_WORLD, worldPos_->GetMatrix());
	if (FAILED(device_->SetStreamSource(0, vertexBuffer_, 0, sizeof(Vertex))))
		return E_FAIL;
	if (FAILED(device_->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2)))
		return E_FAIL;
	return S_OK;
}

thanks for any help, if you have any questions I'll try to answer them.
Advertisement
Hi there Phreaky19,
How are you doing?

[How is a device lost?]
"By design, the full set of scenarios that can cause a device to become lost is not specified. Some typical examples include loss of focus, such as when the user presses ALT+TAB or when a system dialog is initialized. Devices can also be lost due to a power management event, or when another application assumes full-screen operation. In addition, any failure from IDirect3DDevice9::Reset puts the device into a lost state. "

[What happens to the resources?]
"A lost device must re-create resources (including video memory resources) after it has been reset. If a device is lost, the application queries the device to see if it can be restored to the operational state. If not, the application waits until the device can be restored.

If the device can be restored, the application prepares the device by destroying all video-memory resources and any swap chains. Then, the application calls the IDirect3DDevice9::Reset method. Reset is the only method that has an effect when a device is lost, and is the only method by which an application can change the device from a lost to an operational state. Reset will fail unless the application releases all resources that are allocated in D3DPOOL_DEFAULT, including those created by the IDirect3DDevice9::CreateRenderTarget and IDirect3DDevice9::CreateDepthStencilSurface methods."

[What qualifies the resources that need to be reset?]
"All video memory must be released before a device can be reset from a lost state to an operational state. This means that the application should release any swap chains created with IDirect3DDevice9::CreateAdditionalSwapChain and any resources placed in the D3DPOOL_DEFAULT memory class. The application need not release resources in the D3DPOOL_MANAGED or D3DPOOL_SYSTEMMEM memory classes. Other state data is automatically destroyed by the transition to an operational state."

Check at the IDirect3DDevice9::present method that the device is lost or not and then reset the device accordingly,

The Present Method returns
"D3DERR_DEVICELOST The device has been lost but cannot be reset at this time. Therefore, rendering is not possible."

Sorry for the long post. This might help others that come here.
Looks from your code that you aren't checking if the device is lost at the Present method.
Quote:Original post by Phreaky19
However, when I alt-tab out and back in the polygon is not there. It doesn't give me an error and just keeps on running.


Have you run your application with the debug runtimes? Have a look at this if you're not familiar with the debug runtimes

Things like this usually pop up in the debug spew as either a warning or error, apart from the severe errors your application may not getting anything more than a bad return code (but you seem to be checking all of those).


I would go with checking your lost-device code as per Armadon's post.

hth
Jack

<hr align="left" width="25%" />
Jack Hoxley <small>[</small><small> Forum FAQ | Revised FAQ | MVP Profile | Developer Journal ]</small>

This topic is closed to new replies.

Advertisement