• Advertisement

Archived

This topic is now archived and is closed to further replies.

CreateVertexBuffer fails

This topic is 5305 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I''ve never had this problem before and it seemed to hit me out of nowhere. I was implementing a camera class into my code, when suddenly,
device->CreateVertexBuffer(4096 * sizeof(Vertex), 0, D3DFVF_Vertex, D3DPOOL_DEFAULT, &vbTerrain, NULL 
fails on me. It says that there is an access violation during runtime. I know it isn''t because my device is null, because I''ve tried checking for that immediately before this line, and I set several render states several lines before this call. However, my vertex buffer (vbTerrain) seems to get allocated incorrectly. I can''t ZeroMemory it (that throws an access violation too), and declaring another vertex buffer with a different name yields the same result. I also tried undoing all the changes I made up to before I started implementing the camera class and it still wasn''t working. What could possibly be wrong? Like I said, it just started doing this seemingly for no reason.

Share this post


Link to post
Share on other sites
Advertisement

Forgive me if I''m being patronising (just in case!), but vbTerrain points to an interface of vertex buffer object. You need to lock the vertex buffer to return a memory pointer you can write to.

As a side note, if you are only writing to the buffer once, you might want to make it static when you create it, ensuring the driver will place it in the most optimal memory.

Share this post


Link to post
Share on other sites
Perhaps, but that doesn''t really help me now. I can''t lock the vertex buffer before I create it (while it''s still uninitialized).

However, upon further inspection, I saw that the access violation notification labels 0x0f8b0f8a as the culprit, which is my device. I find this kinda odd, because if I call CreateVertexBuffer in the same function as I create my device, it doesn''t throw an error until I try using the vertex buffer outside of that function. Does LPDIRECT3DDEVICE9 have some kind of issue with scope? Here''s my source for creating my device:

LPDIRECT3D9 d3d = NULL;
LPDIRECT3DDEVICE9 device = NULL;
...
bool Init(HWND hwnd)
{
D3DDISPLAYMODE DisplayMode;
D3DPRESENT_PARAMETERS params;
D3DCAPS9 caps;

ZeroMemory(¶ms, sizeof(params));
ZeroMemory(&device, sizeof(LPDIRECT3DDEVICE9));
d3d = Direct3DCreate9(D3D_SDK_VERSION);

if(d3d == NULL) return false;
if(FAILED(d3d->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &DisplayMode))) return false;
if(FAILED(d3d->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps))) return false;
DWORD vProc = 0;
if(caps.VertexProcessingCaps != 0)
vProc |= D3DCREATE_HARDWARE_VERTEXPROCESSING;
else
vProc |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
DWORD dwMax = caps.MaxPrimitiveCount;

params.Windowed = true;
params.SwapEffect = D3DSWAPEFFECT_DISCARD;
params.BackBufferCount = 1;
params.BackBufferFormat = DisplayMode.Format;
params.EnableAutoDepthStencil = true;
params.AutoDepthStencilFormat = D3DFMT_D16;

if(FAILED(d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, vProc, ¶ms, &device))) return false;
if(device == NULL) return false;
device->SetRenderState(D3DRS_ZENABLE, TRUE);
device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
device->SetRenderState(D3DRS_LIGHTING, FALSE);

D3DXMATRIXA16 proj;
D3DXMatrixPerspectiveFovLH(&proj, 45.0f, 1.0f, 0.1f, 500.0f);
device->SetTransform(D3DTS_PROJECTION, &proj);

D3DXMATRIXA16 View;
D3DXVECTOR3 Eye(0.0f, 5.0f, -37.0f);
D3DXVECTOR3 LookAt(0.0f, 0.0f, 0.0f);
D3DXVECTOR3 Up(0.0f, 1.0f, 0.0f);
D3DXMatrixLookAtLH(&View, &Eye, &LookAt, &Up);
device->SetTransform(D3DTS_VIEW, &View);

return true;
}

Share this post


Link to post
Share on other sites

Well I guess that method looks ok - except you don''t need to zeromemory the device pointer (just tell it to = 0 and its zeroed as its a pointer).

So my guess is your vertex buffer pointer is out of scope somewhere. Of course, its always possible that the device is being invalidated by a mode change or "resize" operation.

Share this post


Link to post
Share on other sites
I tried changing that ZeroMemory line to device = 0;, but that didn''t seem to help. I don''t think my vertex buffer is out of scope, because my device, vertex buffer, and a few other D3D-related objects are global (I know this isn''t good practice but I didn''t feel like making everything object-oriented at my first crack at index buffers).

Share this post


Link to post
Share on other sites
Well really we need more code, because what you''ve shown isn''t the whole story. You need to post what happens in your message loop, because resizing the display can invalidate device objects, which might cause the kind of issue you speak of.

Share this post


Link to post
Share on other sites
Here's my code, but I can't even get it to render one frame before CreateVertexBuffer fails:

// TerrainViewer.cpp : Defines the entry point for the application.

//


#include "stdafx.h"
#include "TerrainViewer.h"
#include "d3d9.h"
#include "d3dx9.h"
#include "CCamera.h"
#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9.lib")
#define D3DFVF_Vertex (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)

#define MAX_LOADSTRING 100

// Global Variables:

HINSTANCE hInst; // current instance

TCHAR szTitle[MAX_LOADSTRING]; // The title bar text

TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name


// Forward declarations of functions included in this code module:

ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
HWND hWindow;

// Direct3D objects

LPDIRECT3D9 d3d = NULL;
LPDIRECT3DDEVICE9 device = NULL;
LPDIRECT3DVERTEXBUFFER9 vbTerrain;
LPDIRECT3DINDEXBUFFER9 ibTerrain = NULL;

// Globals

WORD sIndices[(6 * 63 * 63)]; //these are the order in which to draw the vertices


// Function declarations

bool Init(HWND hwnd);
void Frame();
void ShutDown();
bool InitTerrain();
void GetInput();

struct Vertex
{
float x, y, z;
D3DCOLOR diffuse;
float u, v;
};

Vertex TerrainData[64 * 64];//these are the actual vertices


int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
// TODO: Place code here.

MSG msg;
HACCEL hAccelTable;

// Initialize global strings

LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_TERRAINVIEWER, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);

// Perform application initialization:

if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}

hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_TERRAINVIEWER);
bool bCont = Init(hWindow);
while(bCont)
{
PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE);
if(msg.message == WM_QUIT)
bCont = false;
else
{
Frame();
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
ShutDown();

return 0;
}



//

// FUNCTION: MyRegisterClass()

//

// PURPOSE: Registers the window class.

//

// COMMENTS:

//

// This function and its usage are only necessary if you want this code

// to be compatible with Win32 systems prior to the 'RegisterClassEx'

// function that was added to Windows 95. It is important to call this function

// so that the application will get 'well formed' small icons associated

// with it.

//

ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;

wcex.cbSize = sizeof(WNDCLASSEX);

wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_TERRAINVIEWER);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = (LPCTSTR)IDC_TERRAINVIEWER;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);

return RegisterClassEx(&wcex);
}

//

// FUNCTION: InitInstance(HANDLE, int)

//

// PURPOSE: Saves instance handle and creates main window

//

// COMMENTS:

//

// In this function, we save the instance handle in a global variable and

// create and display the main program window.

//

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;

hInst = hInstance; // Store instance handle in our global variable


hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
hWindow = hWnd;

if (!hWnd)
{
return FALSE;
}

ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);

return TRUE;
}

//

// FUNCTION: WndProc(HWND, unsigned, WORD, LONG)

//

// PURPOSE: Processes messages for the main window.

//

// WM_COMMAND - process the application menu

// WM_PAINT - Paint the main window

// WM_DESTROY - post a quit message and return

//

//

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;

switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:

switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...

EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}

// Message handler for about box.

LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
return TRUE;

case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
break;
}
return FALSE;
}



bool Init(HWND hwnd)
{
D3DDISPLAYMODE DisplayMode;
D3DPRESENT_PARAMETERS params;
D3DCAPS9 caps;

ZeroMemory(¶ms, sizeof(params));
//ZeroMemory(&device, sizeof(LPDIRECT3DDEVICE9));

device = 0;
d3d = Direct3DCreate9(D3D_SDK_VERSION);

if(d3d == NULL) return false;
if(FAILED(d3d->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &DisplayMode))) return false;
if(FAILED(d3d->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps))) return false;
DWORD vProc = 0;
if(caps.VertexProcessingCaps != 0)
vProc |= D3DCREATE_HARDWARE_VERTEXPROCESSING;
else
vProc |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
DWORD dwMax = caps.MaxPrimitiveCount;

params.Windowed = true;
params.SwapEffect = D3DSWAPEFFECT_DISCARD;
params.BackBufferCount = 1;
params.BackBufferFormat = DisplayMode.Format;
params.EnableAutoDepthStencil = true;
params.AutoDepthStencilFormat = D3DFMT_D16;

if(FAILED(d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, vProc, ¶ms, &device))) return false;
if(device == NULL) return false;
device->SetRenderState(D3DRS_ZENABLE, TRUE);
device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
device->SetRenderState(D3DRS_LIGHTING, FALSE);

if(!InitTerrain())
return false;

D3DXMATRIXA16 proj;
D3DXMatrixPerspectiveFovLH(&proj, 45.0f, 1.0f, 0.1f, 500.0f);
device->SetTransform(D3DTS_PROJECTION, &proj);

D3DXMATRIXA16 View;
D3DXVECTOR3 Eye(0.0f, 5.0f, -37.0f);
D3DXVECTOR3 LookAt(0.0f, 0.0f, 0.0f);
D3DXVECTOR3 Up(0.0f, 1.0f, 0.0f);
D3DXMatrixLookAtLH(&View, &Eye, &LookAt, &Up);
device->SetTransform(D3DTS_VIEW, &View);

Camera.SetCamera(0.0f, 10.0f, -36.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);

return true;
}
void Frame()
{
device->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
device->BeginScene();

device->SetStreamSource(0, vbTerrain, 0, sizeof(Vertex));
device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 64 * 64, 0, 2 * 63 * 63);

device->EndScene();
device->Present(NULL, NULL, NULL, NULL);
}
void ShutDown()
{
if(device != NULL)
{
device->Release();
device = NULL;
}
if(d3d != NULL)
{
d3d->Release();
d3d = NULL;
}
if(vbTerrain != NULL)
{
vbTerrain->Release();
vbTerrain = NULL;
}
if(ibTerrain != NULL)
{
ibTerrain->Release();
ibTerrain = NULL;
}
}
bool InitTerrain()
{
int nCount = 0;
ZeroMemory(TerrainData, sizeof(TerrainData));
for(int i = 0; i < 64; i++)
{
for(int j = 0; j < 64; j++)
{
nHeightArray[i][j] = 0;
Vertex vTemp = {(float)(-32 + i), 0, (float)(-32 + j), D3DCOLOR_XRGB(255, 255, 255), 0.0f, 0.0f};
TerrainData[nCount++] = vTemp;
}
}
nCount = 0;
ZeroMemory(sIndices, sizeof(sIndices));
for(int i = 0; i < 4032; i += 64)
{
for(int j = 0; j < 64; j++)
{
sIndices[nCount++] = i + j;
sIndices[nCount++] = i + j + 1;
sIndices[nCount++] = i + j + 64;
sIndices[nCount++] = i + j + 64 + 1;
sIndices[nCount++] = i + j + 64;
sIndices[nCount++] = i + j + 1;
}
}



//Create Vertex Buffer

vbTerrain = NULL;
//ZeroMemory(vbTerrain, sizeof(vbTerrain));

if(FAILED(device->CreateVertexBuffer(4096 * sizeof(Vertex), 0, D3DFVF_Vertex, D3DPOOL_DEFAULT, &vbTerrain, NULL)))
return false;
Vertex *Vertices;
if(FAILED(vbTerrain->Lock(0, sizeof(TerrainData), (void**)&Vertices, 0)))
return false;
memcpy(Vertices, TerrainData, sizeof(TerrainData));
vbTerrain->Unlock();

//Create Index Buffer

int nIndexListSize = sizeof(WORD) * nCount;
if(FAILED(device->CreateIndexBuffer(nIndexListSize, 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &ibTerrain, NULL)))
return false;
VOID* indices;
if(FAILED(ibTerrain->Lock(0, 0, (VOID**)&indices, 0)))
return false;
memcpy(indices, sIndices, sizeof(sIndices));
ibTerrain->Unlock();

device->SetIndices(ibTerrain);
device->SetFVF(D3DFVF_Vertex);
device->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);

return true;
}


[edited by - langguy on August 18, 2003 4:34:56 PM]

Share this post


Link to post
Share on other sites

Ok, well I''ve got some problems with your code, the first of which is you are more or less ALWAYS going to get an error when you shutdown, because you are deleting your device before you go and delete the vertex buffer. So for starters that could be cleaned up. Secondly, try handling a WM_SIZE message in your message loop. This message should basically shutdown, then recreate the device context and all of the device dependant objects you own.

The thing is, its possible to invalidate device objects on WM_SIZE messages. Basically you are not guaranteed any given IDirect3DDevice9 pointer is valid after this operation.

Share this post


Link to post
Share on other sites
okay, I changed the order in which my objects are released....but I'm not gonna start worrying about handling WM_SIZE quite yet.

While writing this reply, I found out what's crashing my program:


for(int i = 0; i < 4032; i += 64)
{
for(int j = 0; j < 64; j++)
{
sIndices[nCount++] = i + j;
sIndices[nCount++] = i + j + 1;
sIndices[nCount++] = i + j + 64;
sIndices[nCount++] = i + j + 64 + 1;
sIndices[nCount++] = i + j + 64;
sIndices[nCount++] = i + j + 1;
}
}

If I comment out one of these "sIndices[nCount++] = ..." lines, my code proceeds as it should (minus the fact my index buffer isn't completely filled.) This is kinda odd, because this block of code doesn't seem to have anything to do with whether device and vbTerrain are valid or not.

EDIT: Yes! I fixed it! I changed j < 64; to j < 63;. I guess I was writing my indices beyond the memory for sIndices and into device and vbTerrain!

[edited by - langguy on August 18, 2003 5:27:47 PM]

Share this post


Link to post
Share on other sites

  • Advertisement