Post Reply 
 
Thread Rating:
  • 0 Votes - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
A better way to handle texture scale/cache
06-23-2014, 07:54 PM (This post was last modified: 06-23-2014 08:09 PM by RadarNyan.)
Post: #10
RE: A better way to handle texture scale/cache
Let me describe what I have in mind. All codes are pseudo-code.

1) A texture (let's say 0x09658640, 128*128, format 3) is being used to draw something on screen


We use the information of this texture that is "reliable" (well, more reliable than RAM hash) in this case, let's say "0x09658640_128_128_3". We can make it shorter by hash it if we want, or just use it anyway. I'll use "KEY" to represent "0x09658640_128_128_3" in the following description.

Quote:Let me descript the TextureCache design of mine first for the following description:

TextureCache[KEY][0]->TEX : Processed texture (color convert, scale, etc) like we currently have in cache method.
TextureCache[KEY][0]->RAW : RAW memory data from the entire 128x128 range, don't care if it's all texture or not.
TextureCache[KEY][0]->HASH(array) : An array contains several hash that matches this cache entry.

Since a same address could be totally used by different texture, a INDEX ("[0]") is needed.

2) We create a hash of this texture

But we don't hash the entire texture (128x128) like we're currently doing.
Instead of hashing to the end (line 128), we only hash to the last used line (let's say 100).

Code:
HASH1 = DoQuickHash(DATA_MEMORY, 128, 100, format 3)

(DATA_MEMORY is what we think the texture is in memory, which is the thing we're hashing in current method)

3) We check if we have a cache hit

Code:
Loop {
    _INDEX_ = 0

    for _HASH_ in TextureCache[KEY][_INDEX_]->HASH(array){
        if _HASH_ == null { // We reached a "empty" spot, which means we don't get a cache hit
            break the Loop
        } else if _HASH_ == HASH1 { // We got a cache hit
            return TextureCache[KEY][_INDEX_]->TEX
        }
    }

    // Don't give up yet! (this is why we keep copies of RAW data in TextureCache)
    HASH2 = DoQuickHash(TextureCache[KEY][0]->RAW, 128, 100, format 3)
    If HASH2 == HASH1 { // We got a cache hit
        // Add this HASH to the array
        TextureCache[KEY][_INDEX_]->HASH(array).add(HASH1)
        // Return the texture
        return TextureCache[KEY][_INDEX_]->TEX
    }

    _INTEX_++
}

4) Process the texture, make a new texture entry

We can only reach this step if we do not have a cache hit, and by the time it breaks the loop, _INTEX_ will be the INDEX we should use for our cache entry. let's just use 1 in the following description, it will be 0 if it's the first time the texture is loaded of course.

Code:
TextureCache[KEY][1]->RAW = DATA_MEMORY
DoProcessTexture(DATA_MEMORY) // I'm assuming DoProcessTexture function modified original data
TextureCache[KEY][1]->TEX = DATA_MEMORY
TextureCache[KEY][0]->HASH(array).add(HASH1)

5) Return the processed texture

Code:
return DATA_MEMORY

Pros

1. Getting much more cache hit than current method

2. Kind of having a unique ID of a texture, we may use it for texture replacing, or save texture cache to disk for speed up.

Cons

1. DoQuickHash method is called when every single draw, once or twice

Which is way more frequently than what we're currently doing - only hash once while binding a texture.

I'm not sure how fast this DoQuickHash method is, maybe we need something faster, or this very frequent hashing might kill us.

2. Some memory can not be purged if we want to get the unique ID correctly

We can clear TextureCache[KEY][INDEX]->TEX since we can always regenerate it from TextureCache[KEY][INDEX]->RAW, but TextureCache[KEY][INDEX]->RAW and TextureCache[KEY][INDEX]->HASH(array) must not be purged or we will get wrong ID (wouldn't be a problem if we don't want this ID though)

This can be solved if we write the TextureCache to disk, Something like:

Quote:0x09658640_128_128_3_0.png (processed texture)
0x09658640_128_128_3_0.raw (RAW memory dump)
0x09658640_128_128_3_0.txt (contains all possible hash to this texture)

so we can load it back as needed, and if we want to do Texture Replace (otherwise why would we need a unique ID?) we need a dump function anyway. We do not have to manually make texture packs, just dump the textures been processed by xBRZ will be a huge success. Well, it's more like a on-disk texture cache instead of a texture pack, but texture pack is also possible since we have the unique ID.

3. We sure will need more memory

Let's say if a game have 1GB of textures, we will need at least 2GB (1GB RAW + 1GB cache, and we know the cache can't be just 1GB, if we use texture scale it will be much bigger) memory for this unique ID to work (well, it won't be needed right at the beginning, but sure will reach at least 2GB eventually) Most desktop PCs these days doesn't hurt from this at all but all mobile device will suffer from this huge memory hog.

This can be solved if we don't want the unique ID anyway - just purge as will. This method will be working just fine for real-time (as long as we don't suffer from the way more frequent hash calculations) truth if we purge the TextureCache, we sure will loose some possible cache hit, but I believe the hit rate is still better than current method.

This can also be solved with the solution of "purge"-to-disk or cache-on-disk, once we need it, we can purge both TextureCache[KEY][INDEX]->TEX and TextureCache[KEY][INDEX]->RAW. TextureCache[KEY][INDEX]->HASH(array) wouldn't take too much memory anyway so we don't even need to think about it.
Find all posts by this user
Quote this message in a reply
Post Reply 


Messages In This Thread
RE: A better way to handle texture scale/cache - RadarNyan - 06-23-2014 07:54 PM

Forum Jump: