While implementing OpenGL's mipmap generation method into SOIL library I have started to create a test that would verify my initial assumptions. I wanted to test if the new method is faster than the original way. New method seems to be very fast: even 8X faster than the original (for NPOT textures)! And 2X faster for POT textures.
The test
LoadM
different imagesN
times and compareSOIL_FLAG_GL_MIPMAPS
withSOIL_FLAG_MIPMAPS
.
The code:
// GL_MIPMAP
{
TestParams paramsMipGL;
paramsMipGL.files = files;
paramsMipGL.numberOfLoads = NUM_LOADS;
paramsMipGL.soilFlags = SOIL_FLAG_GL_MIPMAPS;
paramsMipGL.testName = "FLAG_GL_MIPMAPS";
TestOutputs resultMipGL = LoadTest(paramsMipGL);
CalcaAndPrintTestResult(paramsMipGL, resultMipGL);
}
// MIPMAP soil version
{
TestParams paramsMip;
paramsMip.files = files;
paramsMip.numberOfLoads = NUM_LOADS;
paramsMip.soilFlags = SOIL_FLAG_MIPMAPS;
paramsMip.testName = "FLAG_MIPMAPS";
TestOutputs resultMip = LoadTest(paramsMip);
CalcaAndPrintTestResult(paramsMip, resultMip);
}
Full source code can be found here: soil2 repository Or alternatively here
Notes:
files
- vector of file names of images to load. By default it is lenna1.jpg, lenna2.jpg and lenna3.jpgNUM_LOADS
- number of texture loads to perform. By default it is 50.
Load Test:
i = 0 to NUM_LOADS do
filename = files[ i%num_files ]
tempTex = SOIL_load_OGL_texture(filename, SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID,
_FLAG_);
_FLAG_
=SOIL_FLAG_MIPMAPS
orSOIL_FLAG_GL_MIPMAPS
As you can see the test is quite simple. We just load new textures (from a file) and each time generate a new texture objects. Additionally in the code there are of course time and memory measurements.
Results
Machine 1 (AMD):
- Intel(R) Core(TM) i5-2400 CPU @ 3.10GHz, 4GB Ram
- AMD Radeon HD 5570, latest Catalyst 13.11 Beta
- Windows 8, 64 Bit
Machine 2 (INTEL):
- Intel(R) Core(TM) i5-3427U CPU @ 180GHz, 16GB Ram
- Intel HD 4000,, drivers 9.18 from July
- Windows 7, 64 Bit
NPOT Textures
- lenna1.jpg 540x600, lenna2.jpg 730x612, lenna3.jpg 540x589
- all RGB JPG images see here in bin folder
- Total memory used by pixels (after loading) is 4.15MB (with mipmaps)
- Original soil way will rescale it always to textures 1024x1024, ant in total it will use 3x1024x1024x3 bytes = 9MB. But we have to increase it by 33% (for mipmaps) and we end up with 12MB.
- New method uses 65% less memory for this case. This number will vary, depending on how close image size is to next mipmap. If we have images like 1000x1000 the difference would not be so huge.
POT Textures
- imgmars.jpg 512x512, lenna512.tga 512x512 and lenna_1024.png 1024x1024
- Total memory used (after loading) is 7MB
- There is no difference between the versions. Still glGenerateMipmap will be faster than the original way.
Future directions
Playing with the SOIL library was a very nice experience. Of course I would like to see official SOIL2 release, but probably some more changes need to be implemented first.
I looked at implementing immutable texture storage to the library. The solution is quite simple (add option to use glTexStorage instead of glTexImage), but substantial amount of time is needed to handle all the changes properly. I will let you know when I manage to finish it. Meanwhile you can always use soil to only load pixel data and perform texture uploads to the gpu on your own.
Remarks
- I've merged most of my changes with Spartant's SOIL2 reposotory. I've tried to do soil2 on my own, but I've noticed that Spartan managed to do it a bit better! I would like to thank him for pulling my glGenerateMipmap changes and suggestions!
- Additional thanks goes for Robert Bu who helped me with my original soil_ext repository.
- I've created a simple gist for calculating memory of a texture object: https://gist.github.com/fenbf/7237365