Game Development Community

gfxTextureManager idea

by Konrad Kiss · in Torque 3D Professional · 11/17/2009 (8:03 pm) · 12 replies

I've been working with texture profiles lately, and one thing has been annoying me. Textures are cached regardless of the profile they had when they were loaded. Consider this:

I have a plain Static profile with all defaults. I load it, and it by default doesn't keep its bitmap data. Then I load it again with another profile that has the GFXTextureProfile::KeepBitmap flag set. It will be disregarded. The texture will be found by the hash, but the second profile will be disregarded - so I still won't have the bitmap data for that texture.

I see that there's a TODO comment there, so I guess I'm not the only one missing this. It'd be really cool to have this feature in sometime. Maybe even something that would let you change profile flags on the fly - and reload if needed. I can imagine that this would enable further optimizations when handled well.

#1
11/18/2009 (6:07 am)
Hum... can't say i've seen this issue, but i agree it should be fixed.

Seems like we can just detect that case and reload the texture if new profile has a KeepBitmap flag.

Are there other flags we need to correct like this?
#2
11/18/2009 (6:27 am)
I'm not sure. SystemMemory comes to mind, but I haven't tested that. (I generally seem to have a trouble telling whether a texture is on the GPU or in system memory :)

Also, the lack of a NoMipmap flag on the second instance might need the mips to be generated. or not?

There is also the question of Dynamic and Static. Which one should take precedence over the other? I am guessing that the latter one would be a good choice.
#3
06/11/2010 (2:02 pm)
Has any of this been resolved? As far as I can tell the texture profiles are complete bullshit. I have one with the KeepBitmap flag set, yet I keep getting fatal asserts on getBitmap because the flag is no longer set? WTF?!
#4
06/11/2010 (2:17 pm)
It works the first frame, throws away the bitmap even though it's created with KeepBitmap, then crashes the crap out. Awesome work guys!
#5
06/11/2010 (2:20 pm)
Sounds like a bug if you load the same texture using different profiles.
#6
06/11/2010 (2:26 pm)
My problem is related to having Dynamic and KeepBitmap both set... here's a thought... DONT HAVE FLAGS THAT CONFLICT WITH EACH OTHER! The solution was posted around here a while back and I had implemented it in Alpha... now in Beta and it's not working. Didn't think anything in textures changed but certainly possible!

Of course the Alpha solution was not much of a solution because it still crashed all the damn time because the IsRenderTarget flag would arbitrarily get set (not by me!) and then an assert would quickly follow.

Basically, Torque is not built to handle dynamic textures. I've used dynamically written (real time video stream) textures in 3 or 4 other game engines based in Direct3D without incident. Of course it wouldn't work smoothly in Torque
#7
06/11/2010 (2:28 pm)
To follow up, why are there both STATIC and DYNAMIC flags?! They are opposites. If DYNAMIC is not set, the default behavior should be STATIC. You don't need both! And it's not like the STATIC mask == !DYNAMIC mask. They each occupy different bits in the flag! So it's possible to have both STATIC and DYNAMIC set at once! How in the name of all that's not holy does that make any freakin sense?!
#8
06/11/2010 (2:49 pm)
Aaron, this is not exactly a bug. It's just behavior that is not the most logical, but as I wrote, it's not so easy to find better logic. If you don't watch your flags then its easy to crash stuff.

I'm sure that Manoel is right - you are probably loading that same texture before that.

As for the flags - I really like this system, it does save you a lot of headaches when working with textures. Anyway, to solve your problem temporarily, try this:

GFXTextureObject *GFXTextureManager::_lookupTexture( const char *hashName, const GFXTextureProfile *profile  )
{
   // >>>
   // let's make sure that this always loads the texture and stores the
   // bitmap according to its profile - even if something loaded the same
   // bitmap already
   if (  profile->getProfile() == GFXMyDefaultTargetProfile.getProfile() ) {
      return NULL;
   }
   // <<<

   GFXTextureObject *ret = hashFind( hashName );

   // TODO: Profile checking HERE

   return ret;
}

Give that a try. Define your own target profile first, and replace that GFXMyDefaultTargetProfile with the name of yours. Granted, it's a hack, but at least not a very ugly one. Well, not a very very very ugly one.

Torque might be tough at times, but still, this is just not the right way to act because of some frustrating piece of code. Go ahead and recommend a system that you think would do this better. That'd be a great example of productive criticism. This was not. ;)

Cheers.

Edit: Having both Static and Dynamic bits would be useful if an undefined state had a meaning - ie. if it would assume one state under certain circumstances and the other under others. I don't know if its like that - I'm just saying that in theory there could be value to having two separate bits. Still, you're probably right about it to be honest. But I can't shake off the feeling that there's a very obvious explanation to this that we can't see yet.
#9
06/11/2010 (3:26 pm)
I am loading the texture once and only once. I'll try that code out just to make sure, but I already have conditions all over this biznitch...*I* am certainly not accessing it anywhere else. Dunno what Uncle Torquey decides to do with my data when I'm not looking.

As an aside, the flag system is a nice idea but parts of it's current implementation are flippin' dumb. It is deciding whether there is a valid buffer attached to the texture based on a bit that gets set at time of creation of the texture... It should, MORE CORRECTLY, check that the buffer is indeed non-null.

To demonstrate this dumbness, I just tried this code, which asserts on getBitmap... which is hilarious, because clearly the texture has a valid buffer (pbmpHandleBitmap is a valid GBitmap that is kept around and plays fine on its own).

//ready for copy
if(m_htxtTextureHandle)
{
  m_htxtTextureHandle->set(m_pbmpHandleBitmap, &profile, false, "Itsgonnacrash");
 GFXLockedRect* pRect = m_htxtTextureHandle->lock();
 if(pRect)
   U32 thisisfunny = htxtTextureHandle->getBitmap()->getWidth()
Handle is valid, bitmap is valid. Locks a-ok, but that getBitmap() explodes all over the place because I don't have KeepBitmap flag set in the profile. How accurate is that flag system and AssertFatal now?

This is playing devils advocate, sure. But using KeepBitmap in the context of a dynamically written texture causes it's own set of problems (there are threads around here about it, don't feel like linking).

Constructive? I'm never working with Torque again after next week! I'm so happy to be going back to Ogre 3D, working with a full-featured, stable directx based rendering engine. And then I'll also be starting to work on some Unity based projects. Pretty constructive i'd say ;-) ;-)
#10
06/11/2010 (3:47 pm)
Its how the system works. If you need that bitmap, set the flag so. If you don't then don't. That bitmap is going to be discarded soon because the flag is not set - so that assert is probably saving you from something worse. Perhaps you wouldn't, but others could assign pointers to that bitmap and that could cause uglier problems just a little later on - the issue would be harder to catch by then. There's always another perspective to look at things I guess.

You should use the engine that you're most satisfied with and that lets you prototype your ideas as you like. Ogre 3D is a great engine and so is Unity!

While Torque 3D is superior, it does require more patience, I agree with that.

Good luck!
#11
06/11/2010 (4:50 pm)
Right, I'm impatient because I have to double my timeline for every project due to the fact that thousands of lines of engine code have to be added or modified every week to get very basic functionality into Torque, e.g. dynamic textures. Fine, be smug if you'd like. It is the internet after all :-)

Anyway, no, that's not how the system works. I have a ref-counted GBitmap with a valid buffer. This is not going away until I release the buffer or release the ref. Yes, I might have to refresh a texture here or there if I want to keep the graphics card copy of the buffer up-to-date, since Torque is not doing it for me. But no, there will not be a crash. No one touches that GBitmap but me. The texture is not available in any editor. Everything will work fine... if I remove those asserts.

Torque is asserting fatal based on the possibility that, due to user defined characteristics of the bitmap, it *might* become invalid sometime in the future. (This is what you just said). Imagine if Windows or any critical system did this. Your cruise control would crash your car as if it was a Toyota. You couldn't check your email without a bsod.

No engine is superior. I've looked in depth at most of those in the indie / academic price range. All have warts, Torque looks great until you get in the engine code and then it's very messy because it's 15 year old code patched over and over again.
#12
06/12/2010 (12:28 am)
There's a lot of truth in what you say, Aaron, and I don't want to argue with you. The problem definitely needs a more thorough investigation. What I was a little bit bitter about was the manner in which you continued to present your issues.