Jump to content

  • Log In with Google      Sign In   
  • Create Account

Awesome job so far everyone! Please give us your feedback on how our article efforts are going. We still need more finished articles for our May contest theme: Remake the Classics

Erik Rufelt

Member Since 17 Apr 2002
Offline Last Active Yesterday, 10:23 AM
*****

#4779183 Best way to achieve fast 2D these days

Posted by Erik Rufelt on 25 February 2011 - 06:41 PM

Yes it should be faster. OpenGL/D3D can easily fill up the PCI Express bandwidth with their normal texture update functions, and as long as you just write and don't read from the frame-buffer it's usually not a problem to write directly to the back-buffer either, if you can get access.

Here's a minimal example I've used in the past. If you want perfect performance, it's probably a better idea to use a system-memory texture and then upload that instead, perhaps even with a ring-buffer of 2-3 textures to increase parallelism, but this is a bit shorter.
#include <windows.h>
#include <D3D9.h>

typedef IDirect3D9* (WINAPI * PFNDIRECT3DCREATE9)(UINT SDKVersion);

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

void renderFrame(BYTE *buffer, UINT rowBytes, UINT width, UINT height);

// Main
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
	// Load D3D9
	HMODULE hD3D9Lib = LoadLibrary(TEXT("d3d9.dll"));
	PFNDIRECT3DCREATE9 pDirect3DCreate9 = (PFNDIRECT3DCREATE9)GetProcAddress(hD3D9Lib, "Direct3DCreate9");
	if(hD3D9Lib == NULL || pDirect3DCreate9 == NULL) {
		MessageBox(NULL, TEXT("Failed to load D3D9"), TEXT("Error"), MB_OK);
		return 0;
	}
	
	// D3D9
	LPDIRECT3D9 pD3D9 = pDirect3DCreate9(D3D_SDK_VERSION);
	if(pD3D9 == NULL) {
		MessageBox(NULL, TEXT("Direct3DCreate9 failed"), TEXT("Error"), MB_OK);
		return 0;
	}
	
	// Register windowclass
	WNDCLASSEX wc;
	ZeroMemory(&wc, sizeof(wc));
	wc.cbSize = sizeof(wc);
	wc.lpszClassName = TEXT("MyClass");
	wc.hInstance = hInstance;
	wc.lpfnWndProc = WndProc;
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	RegisterClassEx(&wc);
	
	// Create window
	int screenWidth = 1024;
	int screenHeight = 768;
	
	DWORD windowExStyle = WS_EX_OVERLAPPEDWINDOW;
	DWORD windowStyle = WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
	RECT windowRect;
	SetRect(&windowRect, 0, 0, screenWidth, screenHeight);
	AdjustWindowRectEx(&windowRect, windowStyle, FALSE, windowExStyle);
	
	HWND hWnd = CreateWindowEx(
		windowExStyle,
		wc.lpszClassName,
		TEXT("D3D9 Window"),
		windowStyle,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		windowRect.right - windowRect.left,
		windowRect.bottom - windowRect.top,
		NULL,
		NULL,
		hInstance,
		NULL
	);
	
	// Device
	LPDIRECT3DDEVICE9 pDevice;
	D3DPRESENT_PARAMETERS pp;
	
	ZeroMemory(&pp, sizeof(pp));
	pp.Windowed = TRUE;
	pp.hDeviceWindow = hWnd;
	pp.SwapEffect = D3DSWAPEFFECT_DISCARD;
	pp.BackBufferFormat = D3DFMT_X8R8G8B8;
	pp.BackBufferCount = 1;
	pp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;//D3DPRESENT_INTERVAL_ONE for vsync
	pp.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
	
	HRESULT hResult = pD3D9->CreateDevice(
		D3DADAPTER_DEFAULT,
		D3DDEVTYPE_HAL,
		hWnd,
		D3DCREATE_SOFTWARE_VERTEXPROCESSING,
		&pp,
		&pDevice
	);
	if(FAILED(hResult)) {
		MessageBox(NULL, TEXT("CreateDevice"), TEXT("Error"), MB_OK);
		return 0;
	}
	
	pD3D9->Release();
	
	// Get back-buffer
	LPDIRECT3DSURFACE9 pBackBuffer;
	
	hResult = pDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer);
	if(FAILED(hResult)) {
		MessageBox(NULL, TEXT("GetBackBuffer"), TEXT("Error"), MB_OK);
		return 0;
	}
	
	// Main loop
	ShowWindow(hWnd, nCmdShow);
	
	while(true) {
		MSG msg;
		if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) != 0) {
			if(msg.message == WM_QUIT)
				break;
			else {
				TranslateMessage(&msg);
				DispatchMessage(&msg);
			}
		}
		else {
			// Draw frame
			pDevice->BeginScene();
			
			D3DSURFACE_DESC backBufferDesc;
			pBackBuffer->GetDesc(&backBufferDesc);
			
			D3DLOCKED_RECT lockedRect;
			hResult = pBackBuffer->LockRect(&lockedRect, NULL, D3DLOCK_NOSYSLOCK);
			if(SUCCEEDED(hResult)) {
				renderFrame((BYTE*)lockedRect.pBits, lockedRect.Pitch, backBufferDesc.Width, backBufferDesc.Height);
				
				pBackBuffer->UnlockRect();
			}
			
			// End frame
			pDevice->EndScene();
			
			// Present to screen
			if(FAILED(pDevice->Present(NULL, NULL, NULL, NULL))) {
				Sleep(100);
			}
		}
	}
	
	// Release
	pBackBuffer->Release();
	pDevice->Release();
	
	UnregisterClass(wc.lpszClassName, hInstance);
	
	FreeLibrary(hD3D9Lib);
	
	return 0;
}

// Window procedure
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
	switch(msg) {
		// Window destroyed
		case WM_DESTROY:
			PostQuitMessage(0);
		return 0;
	}
	
	return DefWindowProc(hWnd, msg, wParam, lParam);
}

// Render
void renderFrame(BYTE *buffer, UINT rowBytes, UINT width, UINT height) {
	for(UINT i=0;i<height;++i) {
		UINT32 *line = (UINT32*)(buffer + i * rowBytes);
		
		UINT red = rand() & 0xff;
		UINT green = rand() & 0xff;
		UINT blue = rand() & 0xff;
		
		for(UINT j=0;j<width;++j) {
			line[j] = (red << 16) | (green << 8) | blue;
			
			--red &= 0xff;
			++green &= 0xff;
		}
	}
}



#4778851 Do people really help each other in this forum?

Posted by Erik Rufelt on 25 February 2011 - 04:54 AM

Maybe there's a bug, cause I remember viewing your post yesterday and also checked it now, but it still says 0 views...
As for the answer to your problem, I have no idea, as I'm not even sure what exactly the problem is. Try editing your post to include a couple of images of the problem.

Also, being angry cause no one helps you is dumb. This is a free forum with people helping others for free, so it's really up to you to make people feel interested in your problem and want to spend their own time helping you.

One problem with your post is that reading and analyzing your whole shader code for someone that never saw it before, and can't test it, is 10x more work than it is for you that has it up and running. It's almost like you're asking someone to do hard work for you since you can't be bothered to do easy work, which will put most people off.

To make it easier for people to help you, try making a minimal example contained in a single code-box (or max one source + one shader), that we can paste into VC++ and press F5 to immediately see the same results you do. Combine this with a couple of images of the problem to get people interested enough to run your code. This also has the benefit of making everything more clear to yourself, and might help you find a mistake you have overlooked. I have often started to compose a post, and while working on making my problem 100% clear to others reading it, I have also made it clearer to myself, and seen the answer before having to actually post.


#4778846 empty window

Posted by Erik Rufelt on 25 February 2011 - 04:27 AM

You only call Render in WM_CREATE, which is called from within CreateWindow before the window is ever put on screen by ShowWindow. You need to handle repainting the window whenever it becomes visible. In a game, you usually have a game-loop that repaints all the time, and in application that don't continuously update you handle WM_PAINT.

Try setting hbrBackground of your window-class to NULL, and add a Render() before your while(GetMessage()) loop, which should be enough to display your image. If you drag the window around outside the screen you will notice how it's not updating.

It's also preferable to change the loop to while(GetMessage() > 0)), and you can remove UpdateWindow.

If you want continuous updates then change your main message loop to something like this:
MSG msg; 
 
while(true) {
   if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
       if(msg.message == WM_QUIT)
           break;
       else {
           TranslateMessage(&msg);         
           DispatchMessage(&msg);
       }
   }
   else {
       Render();
   }
}



#4778574 Display mode options

Posted by Erik Rufelt on 24 February 2011 - 01:16 PM

I personally like a "show all modes" checkbox next to the short list of resolutions. I doubt anyone would want to use 16-bit color anymore, but refresh rate can be a good thing to be able to change.


#4777203 Raw Input forces camera movement depending on frame time!

Posted by Erik Rufelt on 21 February 2011 - 02:52 PM

One solution is to multiple the movement speed by the frame-time. So if you have 300 FPS, your frame-time is dt = 1.0 / 300.0, and if you have 40 FPS your frame-time is dt = 1.0 / 40.0. Then you set float dr = 300.0f * 15.f * dt; to correct the movement speed so you always get the same speed no matter how many frames you have.


#4777002 game loop problem

Posted by Erik Rufelt on 21 February 2011 - 07:33 AM

You need to use PeekMessage instead of GetMessage, as GetMessage will block and wait when there are no messages.
while(loop) {
  if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }
  else {
    No messages, handle a game frame
  }
}



#4776975 Alternative to an edit control.

Posted by Erik Rufelt on 21 February 2011 - 04:25 AM

I would go for a rich edit control, it's not overkill at all for displaying text with different colors or styles.


#4775766 I got beat up by a cop

Posted by Erik Rufelt on 18 February 2011 - 03:07 AM

Funny as that is, it was very irresponsible and might very well have kept the police from catching a real criminal that night. If he had held you down and beat you with his baton after handcuffing you, then you should have filed a complaint, but for other reasons. It sounds like he punched you to stop you from closing the door, in other words just doing his job. As others have pointed out running is pretty obviously probable cause for a search.

That he called and apologized at all says pretty much about how understanding he is with jackass kids, as it's probably you who should be the one to apologize. Preferably to the girl that was raped in the alley behind the club while all the police were caught up with a joker.

At least now you got a funny story to tell people for years to come, so definitely let it go. =) Stop before someone else gets hurt from your prank.


#4774247 How do I show a child window on top of a backbuffer

Posted by Erik Rufelt on 14 February 2011 - 03:18 PM

Add the WS_CLIPCHILDREN and the WS_CLIPSIBLINGS window-styles, which should prevent any overdraw between your windows and child-windows.


#4774233 Using MSVC++ compiler from command line

Posted by Erik Rufelt on 14 February 2011 - 02:31 PM

Try Building on the Command Line at MSDN.


#4773680 [SOLVED] DrawIndexedPrimitive very slow, but only on ATI

Posted by Erik Rufelt on 13 February 2011 - 10:39 AM

Are you using D3DUSAGE_WRITEONLY when creating your D3DPOOOL_DEFAULT buffers?


#4767991 OpenGL Multithreading

Posted by Erik Rufelt on 01 February 2011 - 10:01 AM

You need synchronization, as your whole program is pretty much a race-condition. Do you know how to use mutexes?
If you really need to SwapBuffers in a different thread from where you render, then you need to place critical sections to make sure the threads don't try to compete about the context, but agree on a time and place to switch who owns it. There can only be one owner at a time. Also, you can't just keep swapping in a different thread without rendering in between, or you will get flickering instead, unless you choose a pixel-format that copies the image instead of swapping the buffers.
Normally, you want to do it like this:
1. RenderOneFrame()
2. SwapOnce()
3. RepeatFrom_1()

Using two threads seems like a very bad design decision, but if you really want it, then look into synchronization between threads and possibly keeping the rendered image in a bitmap or something so you don't need to use SwapBuffers.


#4766823 Minimizing draw calls improves performance?

Posted by Erik Rufelt on 29 January 2011 - 05:11 PM

It can be true. In your case you have nothing to gain as 25 draw-calls is nothing for 600k tris. If your model had only 600 tris however, and you draw 1000 copies of it, then you should look into options for minimizing the calls.


#4766289 [SOLVED] Polygon being drawn entirely black

Posted by Erik Rufelt on 28 January 2011 - 12:38 PM

Try using g_pD3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE), as lighting is enabled by default and requires normals.


#4764989 DirectX 10 to DirectX11

Posted by Erik Rufelt on 26 January 2011 - 04:57 AM

It's not very difficult to switch to OpenGL, but you'll have to rewrite all the code dealing with the API. DX10 to DX11 is pretty much just changing the zero to a one and recompiling, while OpenGL has a quite different API. It does the same things though, so you won't have to learn many new concepts, just a different syntax and API model.




PARTNERS