switching gfx mode crashes bmx
Archives Forums/BlitzMax Bug Reports/switching gfx mode crashes bmx
| ||
Hi I got a report from portals that switching full screen / windowed mode in my game crashes it. It looks like the issue is running out of RAM / VRAM when Graphics command is called multiple times. Piece of code: Strict 'Import odd.aspect Global m, i Global img:TImage[100] For i=0 To 99 img[i] = LoadImage(CreatePixmap(800, 600, PF_RGBA8888)) Next i=0 While Not KeyHit(KEY_ESCAPE) Print i Graphics 800, 600', m*32 ' SetAspectResolution 800, 600, ASPECT_LETTERBOX_BORDER DrawImage img[i Mod 99], 0, 0 Flip m = 1-m i:+1 Wend This code just creates new windowed mode every flip because it's easier to watch Task Manager when the screen doesn't flicker, but it doesn't matter if you make it go back and forth. The number of times you have to recreate Graphics depends on your video card. If you have something powerful it will take longer, if you are on netbook or on awesome integrated card it will happen sooner. In my case sample program crashes on 104 iteration. On my friends comp it crashes on 156. Of course no one will switch modes that many times, but in my game that is quite art heavy it is enough to switch 5 times to crash it on Samsung NC10 (and memory usage before starting switching modes is around 300MB). Memory usage is bigger with every image drawn (which is natural), but also with every call to Graphics (in my game each call added ~10MB mem usage and GCCollect() before calling Graphics cleared only few bytes). If you replace image with something smaller like 32x32 pixmap you still can notice memory leak. Tested on BMX 1.39 and BMX 1.41. |
| ||
When you say "it crashes" - how?? I ran it twice - the first time the screen froze on iteration 49 and I couldn't even start task manager. The second time it did the same on #46 and upon rebooting my Chrome config file was corrupted... so I am a little reluctant to run it any more. However, two notes from your sample code. First, you aren't using EndGraphics before creating a new graphics context. Second, your program just blats away trying to suck up as much resources as it can, as quick as it can. Really, GC isn't getting a look-in. I'm not saying there's no issue... just perhaps need a more reliable/realistic method of demonstrating it. |
| ||
Bigest problem as GfK mentioned is you're not ending graphics before creating a new context. You shouldn't technically HAVE to I think... but endgraphics would certainly help. Additionally you could be noticing a garbage collector failure like I've reported at http://www.blitzbasic.com/Community/posts.php?topic=91511 |
| ||
EndGraphics doesn't help you, because it is built in Graphics command - check the sources for Graphics command. When it crashes it means that I receive debugger message saying "Unhandled Exception: Attempt to access field or method of Null object". In my code it points to DrawImage, but generally this is the first instruction that needs to use Graphics context. My system seems to be more stable than yours GfK ;-) |
| ||
Why are you creating 100 images of 800x600? You specify each as 32 bit images, which is 4 bytes per pixel. 800x600x4 is roughly 2Mb per image. So you're creating something like 200Mb worth of images on memory! I guess the problem is not on Graphics... but on Drawimage. just try: if (img[i mod 99]) then DrawImage img[i Mod 99], 0, 0 To avoid drawing null images that couldn't be created due to lack of memory. EDIT: just tested it here on BMAX 1.28 - no problem whatsoever using my null image test. |
| ||
problem is DX9 driver use SetGraphicsDriver GLMax2DDriver() 'or SetGraphicsDriver D3D7Max2DDriver() |
| ||
You specify each as 32 bit images, which is 4 bytes per pixel. 800x600x4 is roughly 2Mb per image. So you're creating something like 200Mb worth of images on memory! Actually, they are stored in nearest-power-of-two format, so 800x600 actually takes up 1024 x1024 x 4 bytes = 4MB per image. At 100 images, that's 400 MB. |
| ||
@SLotman: I use 100 images because I need VRAM to be staffed with images, otherwise it will take forever to crash the program. The thing is that each Graphics command eats extra RAM/VRAM and this crashes program. I can't use (if null then don't draw) - it's a game - if user switches to Window and random image gets out of memory what do you expect the game to do - reload? That would be great, if there was free RAM to load it into. If DX9 is the problem then I kindly ask to fix it :) I can't use OpenGL (portals don't like it) and DX7 might be ugly on Vista/7 (unless I'm wrong) - that's the reason why DX9 is default driver on those systems, isn't it? |
| ||
Hi, i found that bug and fixed it (took whole day to find it). There is memory leak because D3D9Textures are never released when use EndGraphics. here is quick fix: dxgraphics.mod/d3d9graphics.bmx add: import brl.linkedlist Global textures:tlist=new tlist Type TD3D9Texture Field tex:IDirect3DTexture9 End Type and same file type TD3D9Graphics ,Close method: Method Close() If Not _hwnd Return 'Release All Textures For Local tex:TD3D9Texture = EachIn textures tex.tex.Release_ Next textures.clear() CloseD3DDevice If Not _attached DestroyWindow( _hwnd ) EndIf _hwnd = 0 End Method and same file type TD3D9GraphicsDriver add: Function DestroyTexture(tex:IDirect3DTexture9) For Local t:TD3D9Texture = EachIn textures If t.tex<>tex Continue textures.remove(t) Return next End Function Function SaveTexture(tex:IDirect3DTexture9) Local t:TD3D9Texture = New TD3D9Texture t.tex=tex textures.addlast(t) End Function and file D3D9Max2D.mod/D3D9Max2D.bmx type TD3D9ImageFrame, Delete method: Method Delete() If _texture If _seq=GraphicsSeq If _texture=_bound_texture _d3dDev.SetTexture 0,Null _bound_texture = Null EndIf TD3D9GraphicsDriver.destroyTexture(_texture) 'Add This (delete texture from textures list) _texture.Release_ EndIf _texture = Null EndIf End Method and Create method: If _d3dDev.CreateTexture( pow2width,pow2height,levels,usage,format,pool,_texture,Null )<0 d3derr "Unable to create texture~n" Return EndIf TD3D9GraphicsDriver.SaveTexture(_texture) 'Add this line Im now testing first post code with above fixes, and counter is now over 700, but memory usage is still 200-300Mb. |
| ||
Zeke: you are awesome! I will test it on Monday and report how it works for me. |
| ||
Hey Zeke, it all works great, both for the game and the sample code above. Thanks for great work! |
| ||
Should this be included in the next Blitzmax update? |
| ||
I think so. |
| ||
yes. this was just quick copy from dx7 version. (but im using global textures list.. and this may be causing problems if multiple graphics windows is open.. (or atleast slowdown because all textures must be load again, if there is any endgraphics command which clear all textures)) Mark should check and fix this. |
| ||
mark check this... |
| ||
bumpety bump.... :) |
| ||
Hi, Will fix - thanks Zeke! |
| ||
Will fix - thanks Zeke! Hi Mark, any ETA for the fix in the official build? If not, are you just using Zeke's fix? Thanks! |
| ||
I'm using Zeke's code for now. |
| ||
Thanks Zeke, this worked a treat! |
| ||
I know Mark's busy monkeying about, but any ETA yet on how soon a new version will be with this fix included? Just getting back into coding after a lil break and going through and updating everything to latest versions. Oh - I just added Zeke's fix (above) and noticed a problem. The D3D9 module would no longer compile as it said destroyTexture() wasn't defined. Where it says to add two functions, shouldn't they both be methods? I changed them to methods and now it compiles OK. Last edited 2011 |
| ||
Actually something's not right. This code causes a MAV (even in Debug mode) with no specific error, when End is called. Graphics 800,600 Local img:TImage = CreateImage(256,256) SetBlend solidblend SetClsColor 255,0,0 While Not KeyDown(key_escape) Cls DrawImage img,Rand(0,800),Rand(0,600) Flip Wend End |
| ||
boom boom boom boom. i want this thread in your room(to Mark)... ^^ GfK your code works fine here. |
| ||
Just tested the original code by anawiki using v1.42: Memory never went over 300MB in Debug Mode and never over 260MB in Release Mode.... I left it going for over 1300 . Looks good to me :) |
| ||
code works fine here...admittedly memory went up to 400MB, but I left it for over 5000. |