Frame capture
refering to Jack Hoxley in the post Ref Device (http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=781444&SiteID=1)
Jack Hoxley wrote: |
| My current "solution" is to rig up frame-capture into my DXUT framework; I can then use VirtualDUB to stitch a stream of BMP's together as a video. I automate input into the application and then go grab a drink whilst I wait for it to render then come back and check the video results... |
|
This sounds like a great idee, cause i have some questions about this i created a new topic for it.
I din't work much with directx10 cause its just so slow to render using REF. This might be a good solution indeed, cause finally u can see what your code is doing.
I guess it depends on how u write the code, but lets say u have the bitmaps of each screen, create an avi file of it. How do u know how many FPS to use? the result will be different if u make the movie 30FPS or 100FPS. Unlike DX9 code being rendered by hardware i use a timer to calculate the most of the frame move code like rotations. This way it doesn matter if the program runs at 30FPS or 100FPS, the visual result will be the same. If u render in DX10 using REF and u have like 1 frame every 5 seconds, how do u handle that with the timer? i guess it wont work the same way?
Also got to dig into the DX10 code for this, but i guess u create the frame bitmaps the same way like u take a screenshot in DX9 (write texture from surface)
Maybe a solution for the timer might be using a calculated time value. If u create the avi at 30 FPS u know how much time each frame should take (1sec / 30)
You need to implement some sort of "fixed timing" system. If you're using the DXUT framework this is trivial - make the appropriate call to DXUTSetConstantFrameTime() when you're application starts up.
If you're using your own framework then it's upto you to implement - but it shouldn't be too hard. If you've got lots of calls to QueryPerformanceCounter() or GetTickCount() in your code it gets hard, but if you're been clever and abstracted that out to be some sort of utility "GetRunningTime()" (or whatever) then it's easy.
Where you might compute the per-frame delta you instead just return a constant value (1/30 as you suggest). With time-based modelling this "Just Works".
Bare in mind that rendering at 30hz is probably excessive. You can get reasonably good videos from 15hz (but it's noticeably low, so use this as a rough draft) and around 20-25hz is usually sufficient. Have a look into some of the movie/TV standards - you'll see most of them use low 20's for their frame rate.
As for taking a screenshot in D3D10... the following code is what I'm using for non-MSAA'd rendering. I've not had any luck with MSAA (I can enable it, but it doesn't seem to change anything except the performance!).
static
UINT s_FrameNumber = 0;
++s_FrameNumber;
WCHAR wcFilename[512];
StringCchPrintf( wcFilename, 512, L"%s\\Frame %.4d.bmp", wcOutputDirectory, s_FrameNumber );
OutputDebugString( L"Saving frame as '" );
OutputDebugString( wcFilename );
OutputDebugString( L"'...\n" );// Extract the actual back buffer
CComPtr< ID3D10Texture2D > pBackBuffer;
DXUTGetDXGISwapChain()->GetBuffer( 0, __uuidof( ID3D10Texture2D ), reinterpret_cast< void** >( &pBackBuffer ) );// Save the backbuffer directly
if( FAILED( D3DX10SaveTextureToFile( pBackBuffer, D3DX10_IFF_BMP , wcFilename ) ) )
{
ERR_OUT( L"Unable to save back-buffer texture to file!" );
return;
}Put the above code after you've finished all your rendering and it should do the job. Unless I'm missing something, there isn't a call analagous to IDirect3Device9::GetFrontBuffer() for retrieving proper/AA'd screenshots... which is a real shame as it'd be perfect here...
hth
Jack
Great, i will try this ;)
As for the framework, i'm using my own framework for DX9, but i'm just gone do some testing with DX10 so the framework will do the job for now.