Way to get better perf from dx8 with this 2D code?

Started by
8 comments, last by raptorz99 22 years, 8 months ago
Please forgive this extra long post. I don''t see how they allow you to attach files. Below is some I threw together quick from various sources to try and test the performance and feasability of doing 2D in 3D. Unfortuanetly I only get 20 fps when running it interactively through the debugger. Obviously this won''t work for a game. Any suggestions? Different architecture to use, etc? #include #include #include struct PANELVERTEX { FLOAT x, y, z; FLOAT nx, ny, nz; DWORD color; FLOAT u, v; }; #define D3DFVF_PANELVERTEX (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX1) //----------------------------------------------------------------------------- // Global variables //----------------------------------------------------------------------------- LPDIRECT3D8 g_pD3D = NULL; // Used to create the D3DDevice LPDIRECT3DDEVICE8 g_pd3dDevice = NULL; // Our rendering device LPDIRECT3DTEXTURE8 g_pTexture = NULL; const int NUM_OBJS = 400; LPDIRECT3DVERTEXBUFFER8 g_pVertices[NUM_OBJS]; void Render2D(); void MoveTo(int x, int y); //----------------------------------------------------------------------------- // Name: InitD3D() // Desc: Initializes Direct3D //----------------------------------------------------------------------------- HRESULT InitD3D( HWND hWnd ) { // Create the D3D object, which is needed to create the D3DDevice. if( NULL == ( g_pD3D = Direct3DCreate8( D3D_SDK_VERSION ) ) ) return E_FAIL; // Get the current desktop display mode D3DDISPLAYMODE d3ddm; if( FAILED( g_pD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm ) ) ) return E_FAIL; // Set up the structure used to create the D3DDevice. Most parameters are // zeroed out. We set Windowed to TRUE, since we want to do D3D in a // window, and then set the SwapEffect to "discard", which is the most // efficient method of presenting the back buffer to the display. And // we request a back buffer format that matches the current desktop display // format. D3DPRESENT_PARAMETERS d3dpp; ZeroMemory( &d3dpp, sizeof(d3dpp) ); d3dpp.Windowed = TRUE; d3dpp.hDeviceWindow = hWnd; d3dpp.SwapEffect = D3DSWAPEFFECT_FLIP; d3dpp.BackBufferFormat = d3ddm.Format; d3dpp.BackBufferWidth = 640; d3dpp.BackBufferHeight = 480; d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; // Create the Direct3D device. Here we are using the default adapter (most // systems only have one, unless they have multiple graphics hardware cards // installed) and requesting the HAL (which is saying we want the hardware // device rather than a software one). Software vertex processing is // specified since we know it will work on all cards. On cards that support // hardware vertex processing, though, we would see a big performance gain // by specifying hardware vertex processing. if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice ) ) ) { return E_FAIL; } // Device state would normally be set here return S_OK; } //----------------------------------------------------------------------------- // Name: Cleanup() // Desc: Releases all previously initialized objects //----------------------------------------------------------------------------- VOID Cleanup() { if( g_pd3dDevice != NULL) g_pd3dDevice->Release(); if( g_pD3D != NULL) g_pD3D->Release(); } //----------------------------------------------------------------------------- // Name: Render() // Desc: Draws the scene //----------------------------------------------------------------------------- VOID Render() { if( NULL == g_pd3dDevice ) return; // Clear the backbuffer to a blue color g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,255), 1.0f, 0 ); // Begin the scene g_pd3dDevice->BeginScene(); Render2D(); // End the scene g_pd3dDevice->EndScene(); // Present the backbuffer contents to the display g_pd3dDevice->Present( NULL, NULL, NULL, NULL ); } //----------------------------------------------------------------------------- // Name: MsgProc() // Desc: The window''s message handler //----------------------------------------------------------------------------- LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ) { switch( msg ) { case WM_DESTROY: PostQuitMessage( 0 ); return 0; case WM_PAINT: ValidateRect( hWnd, NULL ); return 0; } return DefWindowProc( hWnd, msg, wParam, lParam ); } void Render2D() { for (int i=0; i<20;i++) { for (int j=0; j<20;j++) { //g_pd3dDevice->SetVertexShader(D3DFVF_PANELVERTEX); MoveTo(i * 32 - 316, j * 32 - 224); g_pd3dDevice->SetStreamSource(0, g_pVertices[i*20+j], sizeof(PANELVERTEX)); g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2); } } } void MoveTo(int x, int y) { float fx = (float)x; float fy = (float)y; //static char tmpStr[40]; //sprintf(tmpStr, "x=%f y=%f", fx, fy); //OutputDebugString(tmpStr); D3DXMATRIX Position; D3DXMatrixTranslation(&Position, fx, fy, 0.0f); g_pd3dDevice->SetTransform(D3DTS_WORLD, &Position); } void PostInitialize(float WindowWidth, float WindowHeight) { D3DXMATRIX Ortho2D; D3DXMATRIX Identity; D3DXMatrixOrthoLH(&Ortho2D, WindowWidth, WindowHeight, 0.0f, 1.0f); D3DXMatrixIdentity(&Identity); g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &Ortho2D); g_pd3dDevice->SetTransform(D3DTS_WORLD, &Identity); g_pd3dDevice->SetTransform(D3DTS_VIEW, &Identity); g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE); g_pd3dDevice->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_ARGB(0, 255, 255, 255)); float PanelWidth = 32.0f; float PanelHeight = 32.0f; for (int i = 0; iCreateVertexBuffer(4 * sizeof(PANELVERTEX), D3DUSAGE_WRITEONLY, D3DFVF_PANELVERTEX, D3DPOOL_MANAGED, &g_pVertices); PANELVERTEX* pVertices = NULL; g_pVertices->Lock(0, 4 * sizeof(PANELVERTEX), (BYTE**)&pVertices, 0); //Set all the colors to white pVertices[0].color = pVertices[1].color = pVertices[2].color = pVertices[3].color = 0xffffffff; //Set positions and texture coordinates pVertices[0].x = pVertices[3].x = -PanelWidth / 2.0f ; pVertices[1].x = pVertices[2].x = PanelWidth / 2.0f; pVertices[0].y = pVertices[1].y = PanelHeight / 2.0f; pVertices[2].y = pVertices[3].y = -PanelHeight / 2.0f; pVertices[0].z = pVertices[1].z = pVertices[2].z = pVertices[3].z = 1.0f; pVertices[1].u = pVertices[2].u = 1.0f; pVertices[0].u = pVertices[3].u = 0.0f; pVertices[0].v = pVertices[1].v = 0.0f; pVertices[2].v = pVertices[3].v = 1.0f; g_pVertices->Unlock(); } HRESULT hr = D3DXCreateTextureFromFileEx(g_pd3dDevice, "C:\\windows\\desktop\\iso\\isohex16_1\\treets.bmp", 0, 0, 0, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT , 0, NULL, NULL, &g_pTexture); g_pd3dDevice->SetTexture(0, g_pTexture); g_pd3dDevice->SetVertexShader(D3DFVF_PANELVERTEX); } int FPS() { static int nFrameCnt = 0; static DWORD time1 = 0; static DWORD time2 = 0; time2 = timeGetTime(); if (time2 - time1 > 1000) { time1 = time2; int nTmp = nFrameCnt; nFrameCnt = 0; return nTmp; } else { nFrameCnt++; return 0; } } //—————————————————————————– // Name: WinMain() // Desc: The application''s entry point //—————————————————————————– INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT ) { // Register the window class WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, "D3D Tutorial", NULL }; RegisterClassEx( &wc ); // Create the application''s window HWND hWnd = CreateWindow( "D3D Tutorial", "D3D Tutorial 01: CreateDevice", WS_OVERLAPPEDWINDOW, 0, 0, 640, 480, GetDesktopWindow(), NULL, wc.hInstance, NULL ); FILE* fp = fopen("log.log", "w+"); // Initialize Direct3D if( SUCCEEDED( InitD3D( hWnd ) ) ) { PostInitialize(640, 480); // Show the window ShowWindow( hWnd, SW_SHOWDEFAULT ); UpdateWindow( hWnd ); int fps = 0; // Enter the message loop MSG msg; while(1) { if (PeekMessage(&msg, hWnd, 0, 0, PM_REMOVE)) { TranslateMessage( &msg ); DispatchMessage( &msg ); } else { fps = FPS(); if (fps != 0) { static char sTmp[25]; static char sTmp2[25]; itoa(fps, sTmp2, 10); sprintf(sTmp, "%s\n", sTmp2); //fprintf(fp, "%ld\n", fps); OutputDebugString(sTmp); } Render(); } } } fclose(fp); // Clean up everything and exit the app Cleanup(); UnregisterClass( "D3D Tutorial", wc.hInstance ); return 0; } </i>
Advertisement
I couldn''t find anything horrible in your actual rendering code, but writing to a file every frame is certainly suboptimal (and I would do your FPS code differently...)

Look at the onscreen FPS displays in the SDK samples...
Author, "Real Time Rendering Tricks and Techniques in DirectX", "Focus on Curves and Surfaces", A third book on advanced lighting and materials
-- when running it interactively through the debugger

That''s your first optimization... don''t run it through the interactive debugger.

The sprintf() in the main loop is also killing you.

Third, what happens in your Render2D() function? I didn''t see it listed.

Thanks for the replies so far! The render2D function is listed in there.

Also, would I be able to expect that "big" of a jump in FPS while not running through the debugger? I know it slows it down, but I can;''t imagine that it will give me back like 20-30 fps.

I do have a question about the Render2D loop. In there I am transforming each primtive drawn . That amounts to 400 for the simple map squares.

Is this a possible problem? I started doing this because I heard that lockinf the vertex buffer should be avoided at all costs.

Thanks!
quote:Original post by raptorz99
Thanks for the replies so far! The render2D function is listed in there.

Also, would I be able to expect that "big" of a jump in FPS while not running through the debugger? I know it slows it down, but I can;''t imagine that it will give me back like 20-30 fps.

I do have a question about the Render2D loop. In there I am transforming each primtive drawn . That amounts to 400 for the simple map squares.

Is this a possible problem? I started doing this because I heard that lockinf the vertex buffer should be avoided at all costs.

Thanks!

G''day!

Transforming and drawing each panel like that is slowing you down. OutputDebugString isn''t blindingly fast either, calling it every frame is doing bad things to your frame rate.

If these are static panels that don''t move (or rarely move) then transforming them each time is a waste. Create a VB big enough to store them all, transform them your self and then just do 1 big DrawPrim call. It should be a lot faster.




Stay Casual,

Ken
Drunken Hyena
Stay Casual,KenDrunken Hyena
How should I transform them myself? By using Lock() and then having at it or? I was trying everything I could to avoid Lock() if that is the case. I read somewhere that is stalls the graphics pipeline I think.

Thanks!
Hey, HardCore 3D Programmer !

When you want to do 3D games, use VB, IB, and triangle-strip & ...

But when you want to do a 2D games, do a 2D game not a 3d one that''s looking like a 2d game.

Use the interface ID3DXSprite, this interface is coming with D3DX! That''s for 2d!

And as everyone state, NEVER use a IO function in your game loop, no fopen nor fwrite, ...

I think, it''s better having FPS stated on screen than in a file!

Good look! And stop 3d, start 2d!

One more things, i''ve try Dx8 Sprite interface, and i get over 100fps on a 800mHz Duron with 128megs ram and a 32megs 3D Prophet 4500 agp!

The tech-demo was ran in 1024x768, with a tile-map of 10000x10000 with over 100units on the map.

B2Funny

Sorry, one other thing that i want to clear up.

You need to use Lock/Unlock. But if you dont want to get lossy framerate. Use only VertexBuffer for a minimum of 1k polygons. If you''re doing alot of Lock/Unlock on very small VertexBuffer, and i mean, VB with less than 1k polygons. That''s going to be slow.

And as i say before using D3DXSprite Interface you get your 2d game, without Matrix, Vertex Buffer, Transformation Pipeline, ... and every other aspect of a 3d game.

Have a nice day

B2Funny
quote:
Quote by b2funny

And as i say before using D3DXSprite Interface you get your 2d game, without Matrix, Vertex Buffer, Transformation Pipeline, ... and every other aspect of a 3d game.


If you have decided to use D3DXSprite you may d/l my optimized D3DXSprite wrapper with the source included at:

  Downloads:  ZeroOne Realm

  Downloads:  ZeroOne Realm

I haven''t looked at the D3DXSprite interface yet mainly because I heard it is slow. Any fact to this?

Also, is it still possible to use the other 3D benefits of DX8, such as alphablending, fog, lighting, etc, while using the D3DXSprite interface?

Thanks!

This topic is closed to new replies.

Advertisement