Hi all! I'm writing a short game editor type application and I stumbled upon a wierd phenomenon. When loading a model from an .x file I wanted to compute it's bounding box and to my surprise the vertex buffer lock crashes my app every time. The error is:
Quote:
An unhandled exception of type 'System.AccessViolationException' occurred in RAW3D Editor.exe
Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
The same happens when I try calling D3DXCreateBox(). I did some checking and found out that ValidateDevice() returns E_FAIL.
Here's the code:
R3DDevice.h:
#pragma once
#ifndef R3D_DEVICE_H
#define R3D_DEVICE_H
namespace RAW3DEditor
{
namespace R3DDirect3D
{
class R3DRenderDevice
{
public:
R3DRenderDevice();
void Release();
void ToggleRendering() {RenderingEnabled = !RenderingEnabled;};
void EnableRendering() {RenderingEnabled = true;};
void DisableRendering() {RenderingEnabled = false;};
bool GetRenderingEnabled() {return RenderingEnabled;};
protected:
~R3DRenderDevice();
void SetDeviceParameters(int Height, int Width);
public:
HRESULT Render();
HRESULT SetViewport(D3DVIEWPORT9* NewViewport);
HRESULT InitializeD3D(HWND ParentWindow, int Height, int Width);
HRESULT SetBackBuffer(int Height, int Width);
IDirect3DDevice9* GetDevice();
IDirect3DSurface9* GetBackbuffer();
private:
IDirect3D9* Direct3D;
IDirect3DDevice9* Direct3DDevice;
D3DPRESENT_PARAMETERS D3DPresentParams;
HWND Window;
bool RenderingEnabled;
FILE* log;
};
}
}
#endif
R3DDevice.cpp:
#include "stdafx.h"
using namespace RAW3DEditor::R3DDirect3D;
R3DRenderDevice::R3DRenderDevice()
{
SYSTEMTIME LocalTime;
Direct3D = NULL;
Direct3DDevice = NULL;
RenderingEnabled = false;
_wfopen_s(&log, L"R3DRenderLog.log", L"w");
GetLocalTime(&LocalTime);
fwprintf_s(log, L"%02d.%02d.%04d %02d:%02d\n\n", LocalTime.wDay, LocalTime.wMonth,
LocalTime.wYear, LocalTime.wHour, LocalTime.wMinute);
fwprintf_s(log, L"Basic device constructed.\n");
}
R3DRenderDevice::~R3DRenderDevice()
{
if(Direct3D)
Direct3D->Release();
if(Direct3DDevice)
Direct3DDevice->Release();
fwprintf_s(log, L"Device shut down.\n");
fclose(log);
}
HRESULT R3DRenderDevice::SetBackBuffer(int Height, int Width)
{
HRESULT hr;
SetDeviceParameters(Height, Width);
if( SUCCEEDED( hr = Direct3DDevice->Reset(&D3DPresentParams) ) )
fwprintf_s(log, L"Device successfuly reset for %d by %d.\n", Width, Height);
else
fwprintf_s(log, L"Device reset failed for %d by %d.\n", Width, Height);
return D3D_OK;
}
void R3DRenderDevice::SetDeviceParameters(int Height, int Width)
{
D3DFORMAT DetectedDepthFormat, DetectedBackBufferFormat;
int StencilIndex, SurfaceIndex;
BufferFormats* AvailableFormats = new BufferFormats();
HRESULT hr;
for(SurfaceIndex = AvailableFormats->LBackBufferFormats; SurfaceIndex >= 1; SurfaceIndex--)
for(StencilIndex = AvailableFormats->LStencilBufferFormats; StencilIndex >= 1; StencilIndex--)
{
DetectedBackBufferFormat = AvailableFormats->BackBufferFormats[SurfaceIndex];
DetectedDepthFormat = AvailableFormats->StencilBufferFormats[StencilIndex];
if(SUCCEEDED(hr = Direct3D->CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
DetectedBackBufferFormat,
D3DUSAGE_DEPTHSTENCIL,
D3DRTYPE_SURFACE, DetectedDepthFormat) ) )
{
SurfaceIndex = 0;
StencilIndex = 0;
}
}
delete AvailableFormats;
ZeroMemory(&D3DPresentParams, sizeof D3DPRESENT_PARAMETERS);
D3DPresentParams.BackBufferHeight = Height;
D3DPresentParams.BackBufferWidth = Width;
D3DPresentParams.Windowed = TRUE;
D3DPresentParams.AutoDepthStencilFormat = DetectedDepthFormat;
D3DPresentParams.EnableAutoDepthStencil = TRUE;
D3DPresentParams.SwapEffect = D3DSWAPEFFECT_DISCARD;
D3DPresentParams.MultiSampleType = D3DMULTISAMPLE_NONE;
D3DPresentParams.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
D3DPresentParams.BackBufferFormat = DetectedBackBufferFormat;
}
HRESULT R3DRenderDevice::InitializeD3D(HWND ParentWindow, int Height, int Width)
{
HRESULT hr;
Window = ParentWindow;
if( NULL == ( Direct3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
{
fwprintf_s(log, L"Direct3D object creation failed.\n");
return E_FAIL;
}
SetDeviceParameters(Height, Width);
if( FAILED( Direct3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, Window,
D3DCREATE_HARDWARE_VERTEXPROCESSING,
&D3DPresentParams, &Direct3DDevice ) ) )
{
fwprintf_s(log, L"Direct3D device creation failed.\n");
return E_FAIL;
}
if( FAILED( hr = Direct3DDevice->ValidateDevice(NULL) ) )
DXTRACE_ERR( L"Device validation failed", hr );
fprintf_s(log, "Device initialized.\n");
return D3D_OK;
}
HRESULT R3DRenderDevice::Render()
{
if( !Direct3DDevice )
{
fwprintf_s(log, L"Scene rendering failed. Device not initialized or invalid.\n");
return E_FAIL;
}
Direct3DDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(255, 255, 255), 1.0f, 0 );
if( SUCCEEDED( Direct3DDevice->BeginScene() ) )
{
Direct3DDevice->EndScene();
}
else
{
fwprintf_s(log, L"Scene rendering failed.\n");
return E_FAIL;
}
Direct3DDevice->Present( NULL, NULL, NULL, NULL );
return D3D_OK;
}
HRESULT R3DRenderDevice::SetViewport(D3DVIEWPORT9 *NewViewport)
{
if ( FAILED( Direct3DDevice->SetViewport(NewViewport) ) )
{
fwprintf_s(log, L"New viewport has been set successfully\n");
return E_FAIL;
}
return D3D_OK;
}
IDirect3DDevice9* R3DRenderDevice::GetDevice()
{
return this->Direct3DDevice;
}
IDirect3DSurface9* R3DRenderDevice::GetBackbuffer()
{
IDirect3DSurface9* Backbuffer;
HRESULT hr = this->Direct3DDevice->GetBackBuffer( 0, 0, D3DBACKBUFFER_TYPE_MONO, &Backbuffer );
if(SUCCEEDED(hr))
fwprintf_s(log, L"Backbuffer surface retrieved successfuly.\n");
else
fwprintf_s(log, L"Backbuffer surface could not be retrieved.\n");
return Backbuffer;
}
void R3DRenderDevice::Release()
{
this->~R3DRenderDevice();
}
The code that requests device creation is
this->Device = new R3DRenderDevice;
this->Device->InitializeD3D(ClientHWND, ClientHeight, ClientWidth);
Where ClientHWND is the window handle for a class derived form System::Windows::Forms::Panel and the other two parameters represent the size of the panel.
The D3Dobject creation does not encounter any errors and neither does the device creation. I can also reset the device and even some basic drawing works too but when I try to validate the function returns E_FAIL and locking buffers or creating primitives gives the AccessViolationException at runtime.
What's happening ?