{"id":1260,"date":"2011-06-13T17:34:10","date_gmt":"2011-06-13T16:34:10","guid":{"rendered":"http:\/\/positech.co.uk\/cliffsblog\/?p=1260"},"modified":"2011-06-12T18:52:54","modified_gmt":"2011-06-12T17:52:54","slug":"optimising-my-dumb-textures","status":"publish","type":"post","link":"https:\/\/www.positech.co.uk\/cliffsblog\/2011\/06\/13\/optimising-my-dumb-textures\/","title":{"rendered":"Optimising my &#8216;dumb&#8217; textures"},"content":{"rendered":"<p>I have this class in my code called &#8216;smart texture&#8217;. I&#8217;ve had it for several games now. It basically lets me tell a sprite to use &#8220;gun.dds&#8221;, and it transparently converts that to the LPDIRECT3DTEXTURE9\u00a0 and doesn&#8217;t mention it. It keeps &#8216;gun.dds&#8217; in memory, and if I ever lose the screen (alt+tab), and need to rebuild stuff, it will replace the invalid surface pointer the next time it gets drawn with a fresh copy.<\/p>\n<p>MAGIC.<\/p>\n<p>Trouble is, that means keeping a list of every smart texture, so that I don&#8217;t miss any when recovering from alt+tab. That&#8217;s easy, but I ended up using texturedsprites (with a built-in smart texture) everywhere, and thus the list, for a full battle could be 20,000 textures long.<\/p>\n<p>F**k.<\/p>\n<p>So here I am, effectively keeping a record of me trying to fix this&#8230;<\/p>\n<p>It&#8217;s 5.35PM Sunday. The wonders of aqtime show me that when I ditch the current level and load in a new one, I am killing off about 8,000 smart textures. Every one is going through it&#8217;s destructor and removing itself from the smart textured list. This sucks. I need this to be faster. First instinct is to speed up the destructor, but obviously that&#8217;s treating the symptom, not the cause. The real problem is 8,000 smart textures. That isn&#8217;t so smart, when 2,000 of them are probably pointing to the exact SAME surface in directx&#8230; I need to rethink this system, and NOT break any other code&#8230;<\/p>\n<p>I *do* have a system called GUI_TextureCache which does some &#8216;fixed&#8217; storing of textures I use all the time, like UI stuff, buttons etc. This is obviously a similar task to what I want to do here, in that I need a dynamic dumping ground for commonly used textures pointers. I&#8217;m concluding that the cleanest way to handle a fix would be within my SmartTexture itself. it can do some clever caching, and then nobody will ever know any code changed!<\/p>\n<p>Realisation that this means I still keep all these smart textures knocking about, with their &#8216;gun.dds&#8217; strings. That offends me, as a programmer, but tbh, even &#8216;longcomplextexturefilename.dds&#8217; is only 30 characters, so with 2,000 units I&#8217;m wasting 60k here. Big deal.<\/p>\n<p>Right, so the plan is when I call SmartTexture::SetTexture(&#8220;gun.dds&#8221;) it may, or may not add itself to a list of textures that would need rebuilding, based on if its already in the list.<\/p>\n<p>Problem: I can&#8217;t do that, because it means checking the whole list every time I call SetTexture(). That might even be *slower*. However, my current &#8216;SetTexture&#8217; goes through a list to grab the pointer, how slow is that? It looks like currently its about half as much time as all those smarttexture destructors, so it might be a win. Plus my SetTexture() stuff uses a MRU caching system which could make ti super fast when loading in 100 identical units&#8230;<\/p>\n<p>5.50PM Actually realising I&#8217;ll need a totally new class to handle this. it needs to be done a different way, not with existing smart textures. Balls. Surely it can be done? Hold on.. Surely its just a matter of indirection. The purpose of a smart texture is to hold a surface pointer it can rebuild if needed, but it doesn&#8217;t have to hold a direct link. It could actually hold an indirect link.\u00a0 One more piece of pointer indirection is trivial. I just add a new CLoadedTexture class that handles rebuilds, and the smarttextures can point at those, meaning no need to keep a list of them at all, as their pointers never go invalid or need rebuilding.<\/p>\n<p>6.25PM everything coded except the actual rebuild() calls for alt+tab. I&#8217;ll comment the errors out for a quick test&#8230; GAH, it crashes immediately. fixed easily enoguh, and the code RUNS! hurrah, but it doesn&#8217;t seem AMAZINGLY faster,. Quick! to aqtime! what the hell&#8230; it&#8217;s slower?&#8230;<\/p>\n<p>6.35OM. Hah! looking at it backwards, it&#8217;s about 75% faster. how much time does that knock off loading in a new level now? 5.28 seconds down to 2.1 seconds. That&#8217;s pretty good. I&#8217;ll code in the rebuilding stuff and give it a quick test&#8230;<\/p>\n<p>6.50PM Alt+tab doesnt work, I get just a black window, but that may be something else. I&#8217;ve checked in my current code, and am investigating alt+tab issues now. It looks like the restore code hasn&#8217;t worked on this new game at all yet. I consider my (dumb) smart texture code fixed :D<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I have this class in my code called &#8216;smart texture&#8217;. I&#8217;ve had it for several games now. It basically lets me tell a sprite to use &#8220;gun.dds&#8221;, and it transparently converts that to the LPDIRECT3DTEXTURE9\u00a0 and doesn&#8217;t mention it. It keeps &#8216;gun.dds&#8217; in memory, and if I ever lose the screen (alt+tab), and need to<\/p>\n<p class=\"text-right\"><span class=\"screen-reader-text\">Continue Reading&#8230; Optimising my &#8216;dumb&#8217; textures<\/span><a class=\"btn btn-secondary continue-reading\" href=\"https:\/\/www.positech.co.uk\/cliffsblog\/2011\/06\/13\/optimising-my-dumb-textures\/\">Continue Reading&#8230;<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[113,4],"tags":[],"class_list":["post-1260","post","type-post","status-publish","format-standard","hentry","category-game-four","category-programming"],"_links":{"self":[{"href":"https:\/\/www.positech.co.uk\/cliffsblog\/wp-json\/wp\/v2\/posts\/1260","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.positech.co.uk\/cliffsblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.positech.co.uk\/cliffsblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.positech.co.uk\/cliffsblog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.positech.co.uk\/cliffsblog\/wp-json\/wp\/v2\/comments?post=1260"}],"version-history":[{"count":11,"href":"https:\/\/www.positech.co.uk\/cliffsblog\/wp-json\/wp\/v2\/posts\/1260\/revisions"}],"predecessor-version":[{"id":1271,"href":"https:\/\/www.positech.co.uk\/cliffsblog\/wp-json\/wp\/v2\/posts\/1260\/revisions\/1271"}],"wp:attachment":[{"href":"https:\/\/www.positech.co.uk\/cliffsblog\/wp-json\/wp\/v2\/media?parent=1260"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.positech.co.uk\/cliffsblog\/wp-json\/wp\/v2\/categories?post=1260"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.positech.co.uk\/cliffsblog\/wp-json\/wp\/v2\/tags?post=1260"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}