I am guessing that non-mipmapped textures are slower because the entire texture is getting transfered somewhere, not just a low-res mipmap. I am getting like a 60% drop in framerate when I use 3 non-mipmapped 512x512 textures filling the screen. Is this a common occurance? If so, isn’t this a huge obstacle when dealing with shadow maps? Pretty basic question, but I don’t think I have ever dealt with non-mipmapped textures.
Well, mipmapping improves performance, yes As for shadow maps… I don’t think there is a hardware mipmap support for such textures.
Non-mipmapped textures are slower (for minification) because you get texture cache misses all the time. Every time you sample from a location in the texture that is not in the cache, the GPU will read a whole cache line, each consisting of multiple texels. So if your texture accesses for neighboring fragments are not close to each other in texture space, you’ll need several times the texture bandwidth per fragment.
Since cache lines are of fixed size the relative performance drop may be more dramatic the smaller your texels are.
This is something that affects shadow maps as well, but aliasing alone is enough reason for trying to always map about one shadow map texel per screen pixel.
That makes sense…so if a non-mipmapped texture is used, it should be kept close enough to the camera so there are more pixels onscreen than texels in the texture, roughly speaking.
I think you got the basic idea, but it’s not yet quite correct. So long as what you are texturing is close enough to the camera that the next mipmap level would not be used, you should get the same performance as if the texture (object) also had the the next mipmap level.
Imagine texturing a billboard quad with a 1024x1024 texture. So long as the on-screen dimensions of the quad displays > 512x512 pixels, you save no bandwidth using mipmapping. This is the “sweet spot”.
Display the quad as 512x512 on-screen pixels and you have “wasted” 4x bandwidth compared to mipmapped. Display as 256x256 and 16 times as much bandwidth is used than needs to be. Display it in a 16x16 area and you force the GPU to suck in 4096 times the amount of data to display that area (256 pixels visualized by 1Mtexels).
For kicks, imagine displaying a 256x256 area with 16 repeats in both x&y. That’s 1 MegaTimes (newly invented word) compared to using a 16x16 mipmapped texture. Assuming 1024x1024 is stored RGB only (3 bytes/pixel), just to visualize this small area the texture units would have to suck in 1024x1024x3 (3MB) * 256 = 768MB of texture data (with cache misses abound, meaning it’d all be RAM bandwidth) to texture a simple 256x256 billboard. Compare this to having to read a 16x16 texels area (768 bytes in this scenario) that likely fits all in a single texture unit’s cache.
768 bytes vs 768MB of RAM bandwidth used to display that (artifical, but still) billboard… per frame.
Depending on your usage of the texture, it could be faster (even much, much faster) to create a few (or all) mipmap levels for it before using it.
That’s not how it works. Bilinear filtering uses a maximum of four texels, and in the worst case (which is rare) each of those texels belongs to a different cache line. So the maximum bandwidth required for a bilinear texture read is four cache lines, regardless of whether the texture is 1024x1024 or 65536x65536.
I only tested mipmapped vs non-mipmapped textures once. It was on Riva TNT2 and I had a landscape and water in the scene. Textures were about 256x256 and were magnified in at least 50% of the screen area.
Performace difference was about 30-40%.
Of course if you use hi-res textures then improvement will be higher.
Additionally, mipmaps reduce aliasing artifacts. If you use good LOD biad on mipmaps combined with anisotropic filtering, you should get good quality improvement with some performance improvement at the same time.
Having the obvious spelled out, even I now see it. That indeed makes sense (and I suspect it’d also makes for some ugly texturing when minimizing much).
The whole challenge then lies in making sure the texture has more pixels than onscreen, i.e. bilinear filtering is always looking in between two pixels instead of grabbing two pixels that are not adjacent. This is easily detected by visual analysis (it gets grainy).
No. That’s what I tried to convey, that the “sweet spot” is just above half texture dimension (disregarding filtering). It’s more like the challenge is to make sure the displayed area has at least half (quarter) of the texels displayed. If less, mipmapping (downsampling) the texure a level could be beneficial.
That’s what I meant.