I must have spent at least four hours hunting for a simple way to read the current used video memory from my system. I must have done everything at least once. Using the legacy DirectX API, created an OpenGL context to grab it that way, tapped into the WINAPI, used DxDiag, used DXGI and everything in between. You would think this relatively common requirement would be a simple DirectX command, but no, it's wrapped in mystery and riddled with dead-ends. After completely failing in this, I decided on a different approach and used GPU-Z window alongside the loading process and watched for video memory spikes that way. Can't waste days writing a robust video memory monitor when I have game engines to write. If anyone has some 'working' code in C++ that can detect the 'remaining' (not total) amount of video memory on NVIDIA and AMD machines, please do post.
On proceeding the old fashioned way, I did uncover one crucial fact, which lead to a 400MB+ saving on one of my standalone levels. A cheeky claim, as it turns out when you encrypt media, it does not remember it was loaded, and subsequently loads it in again for any other entity that needs the reference. This would include entities of the same type, and more crucially light map textures. My run this morning crashed out at 1GB of video memory, my new test loaded, ran and leveled off at 805MB (673MB when divide all textures by 32) video memory (which included a large uncompressed Church texture which gobbled 128MB all by itself) :) This brief journey puts me in a position where I can load in a lightmapped standalone level now, which is great!
There are still many targets for video memory savings here, and each site needs close study to get the best use of available budget. For now I will finish off my making some new entity asset conversions and then resume Thursday with more winning video saving antics. Sorry for the lack of images, some days are nothing but words and deeds ;)
(Sorry for the lack of images) Not a problem,although i dont understand a lot of the information.I find it interesting trying to find out what it means.
ReplyDeletehey lee my brother who has been writting game engines in c++ for over 20 years suggested this page http://msdn.microsoft.com/en-us/library/bb174526(v=VS.85).aspx
ReplyDeletehttp://developer.download.nvidia.com/opengl/specs/GL_NVX_gpu_memory_info.txt
ReplyDeletehttp://www.opengl.org/registry/specs/ATI/meminfo.txt
GL_NVX_gpu_memory_info needs OpenGL, Reloaded uses DirectX. DXGI only reports total video memory, not 'usage' which is the value I need. Keep 'em coming :)
ReplyDeleteI would still think that you could query the video card for what's available even if the interface is through OpenGL, but I could be wrong. I think it's worth a try.
DeleteTried for 2 hours, no joy. I initialized via InitGlut but the value simply returned zero. If anyone can find code which works from DirectX app but uses the OpenGL mem read, send it along!
ReplyDeleteIf I get some time I'll try a few things and see if I can find something that works. But if you read a lot of the posts on this subject you'll see that most suggest that this is not necessary to know this anyway. Is like I've been saying that you shouldn't really run out if the driver resorts to system memory. So, knowing this value is not really that important.
DeleteUsing managed textures (texture back-ups in system memory) will decrease available system memory, which is something I want to avoid. Knowing the value will allow the use of dynamic texture resizing to allow more textures to be used without worrying about running out of physical video memory.
DeleteProbably won't help, but might be useful :)
ReplyDeletehttp://gamedev.stackexchange.com/questions/4383/how-do-i-query-available-video-memory-using-directx
DX7's GetAvailableVidMem() : We are DX9
ReplyDeleteWMI (Windows Management Interface) has a similar result to the above : Not on W7
DxDiag uses both to give a better result : Returns total, not current usage
D3D9 has a GetAvailableTextureMemory() function, but can only be used on Windows Vista/7 : Returns total, not current usage
Dammit, sorry about that :/
DeleteI found this link too:
http://stackoverflow.com/questions/427707/report-direct3d-memory-usage
It suggests using DirectDraw to somehow retrieve the vram usage, but it makes it clear that's not an accurate way of getting the information, so probably not much help either - It does give a good explanation of why retrieving video memory usage isn't easier though :)
It has to be a C++ code snippet. I already have an external tool called GPU-Z to read the value outside of Reloaded, but I need Reloaded engine itself to trace the usage.
DeleteHere is an example comment about this topic:
ReplyDelete"This is a fairly common question and the basic answer is "You Don't" [smile]
"What do you want to do with this value? The memory managment system is a complex beast and trying to second guess it by micro-managment on your part is unlikely to yield good results for you. Leave the API, XPDM and driver to handle the finer details."
You see?
I want to monitor overall video memory usage as the engine loads in resources, determine if some parts are using too much proportionally and head-off scenarios where too much video memory is being used. Using a system memory back-up is not an option (managed) as I also want to retain as much system memory as possible (and don't want copies of all the textures). Most people can create their games with a specific texture budget in mind, with a game creator your end user could sit there dropping in 64MB textured entities all day long and there needs to be a control here.
DeleteYou can use the EVGA Precision tool to display on screen how much VRAM is currently in use. See this screenshot here: http://mjblosser.com/evga.jpg
ReplyDeleteThanks Mark. I use GPU-Z which has a sensor for video memory used. I just need that same value in the engine itself so I can assign resource loads with apparent video memory usage (to help optimizing).
DeleteYou could try PIX
ReplyDeletehttp://tomtech999.wordpress.com/2011/09/07/debugging-directx-applications-with-pix-for-windows/
Needs to be a C++ code snippet I can integrate into the engine itself.
DeleteAll sounds good, Lee :) Unfortunately I don't believe there is a way to get the current used video memory. You're supposed to only load a sensible amount of stuff into video memory and then leave it up to the driver to handle it efficiently.
ReplyDeleteIf I could convince Reloaded users that a sensible limit has been reached and they can no longer add anything new to their level I would not be very popular. My plan is to dynamically reduce texture sizes as more textures crowd into the video memory itself. Using the system memory as a cache back-up is not an option as I need system memory for other things (many other things).
DeleteThere is a simple DirectX command "D3DKMTQueryStatistics"
ReplyDeleteHere is a link with some info.
http://forum.sysinternals.com/topic26875_post131430.html
Isn't that only for Windows 8?
DeleteI think it works on Windows 7 or later, check this link
DeleteIt is C++ code
https://bitbucket.org/mozilla/projects-ionmonkey/src/5cfb73435e06/gfx/thebes/gfxWindowsPlatform.cpp
Just ran a search for the "gdi32.dll" and its on my Windows 7 machine.
DeleteAh ok cool well maybe that'll help Lee.
DeleteHmm...great link there!! Looks like it's the same hook that GPU-Z uses, which is perfect. Will spend an hour and see where the code takes me...
DeleteYep, this one did it. I will make a blog post today about the whole solution for other would-be DirectX9 coders looking for this most valuable method :)
DeleteMore info on this link
ReplyDeletehttp://processhacker.sourceforge.net/forums/viewtopic.php?t=325
Found more info
Deletehttp://processhacker.sourceforge.net/doc/d3dkmt_8h_source.html
How much memory could be saved by using PNG's instead of DDS? I can have the same image saved in each format and the DDS will be around 16Mb, whereas, the PNG will be 1-2Mb. If we could use those instead, I think that would help things along.
ReplyDeleteIn the case of PNG, file size does not denote memory used. It will uncompress into X8R8G8B8 when loaded. DDS is the best with DXT1 compression in hardware. Also looking at L8 format to see if there is a saving there for lightmaps (pity they don't have an 8-bit compressed surface) :) I might also explore putting four lightmaps into one texture (R,G,B,A) and DXT5 compression. Early days yet...
Delete