Is this code to calculate the datasize of an ARGB8 texture?

Started by
6 comments, last by Hodgman 9 years, 12 months ago

Hi I need to calculate the dataSize of ARGB8 textures with mipmaps.

I made this routine but ti don´t know if is there a minimum size for the mimaps, so I don´t know if it s right


	size=width*height*4;
			mipWidth=width;
			mipHeight=height;
			
			if(mipMaps!=0){
				for(int i=0;i<mipMaps;i++){
					mipWidth/=2;
					mipHeight/=2;
					if(mipHeight<1)
						mipHeight=1;
					if(mipWidth<1)
						mipWidth=1;
					tempSize=mipWidth*mipHeight*4;
					size+=tempSize;
				}
			}
Advertisement

A full MIP map chain ends with the 1x1 texel texture inclusive. But when being used on a GPU, a MIP map chain just needs to be complete, and that may be before the 1x1 texture is reached. So it depends on how the MIP map level limits are chosen.

Your code snippet seems me correct as long as the variable mipMaps doesn't cause the 1x1 texture be considered several times. I.e. the value of mipMaps should be

0 <= mipMaps <= ld( max( width, height ) )

Alternatively also breaking the loop just behind "size+=tempSize;" like so

if (mipHeight==1 && mipWidth==1) break;

would work in this sense.

EDIT: Just for clarification: The ld(x) function in the formula above means the "logarithm dualis", i.e. the logarithm to base 2.

ld( x ) := log2( x )

In case that it isn't available in your favorite math lib, it can be computed by using any other logarithmic function when dividing by the same logarithm of the base. To compute ld when e.g. the natural logarithm or the decimal logarithm is available, this would look like

log2( x ) = loge( x ) / loge( 2 )

log2( x ) = log10( x ) / log10( 2 )

You perhaps want to round to the nearest integer to avoid floating point problems.

Is that "A full MIP map chain ends with the 1x1 texel texture inclusive" also applied to other texture formats like dxt5 or dxt1?


Is that "A full MIP map chain ends with the 1x1 texel texture inclusive" also applied to other texture formats like dxt5 or dxt1?

DXTn is an encoding of texture data. Due to its block nature the last MIP level that fills in the entire block is 4x4 texels. However, with doing some padding one can get down to 1x1 again. Searching for the problem brings e.g. this thread to light, where Evil Steve answers your question in post #5.

Of course, the code snippet in the OP does not consider compression but raw texture data. When considering compression, you should use the mipMaps <= ld( max( width, height ) ) formula instead of the conditional break, and you need to restrict mipHeight and mipWidth to the respective block's edge length instead of 1, and you need to multiply the resulting size with the compression ratio (depending on the compression scheme and sometimes the texel format, but fortunately a fix rate therein).

This is the code I implemented, I thinks it is right but I post it to be reviewed.


	switch(textureFormat){
		
		case DXT5:
			size=width*height;
			mipWidth=width;
			mipHeight=height;
			
			if(mipMaps!=0){
				for(int i=0;i<mipMaps;i++){
					mipWidth=mipWidth/2;
					mipHeight=mipHeight/2;
					blockWidth=mipWidth;
					blockHeight=mipHeight;
					if(mipHeight<1){
						mipHeight=1;
						blockHeight=4;
					}
					if(mipWidth<1){
						mipWidth=1;
						blockWidth=4;
					}
					tempSize=blockHeight*blockWidth;
					if(tempSize<16)
						tempSize=16;
					size+=tempSize;
					 if (mipHeight==1 && mipWidth==1) break;//A full MIP map chain ends with the 1x1 texel texture inclusive
				}
			}
			return size;
			
		case DXT3:
			size=width*height;
			mipWidth=width;
			mipHeight=height;
			
			if(mipMaps!=0){
				for(int i=0;i<mipMaps;i++){
					mipWidth=mipWidth/2;
					mipHeight=mipHeight/2;
					blockWidth=mipWidth;
					blockHeight=mipHeight;
					if(mipHeight<1){
						mipHeight=1;
						blockHeight=4;
					}
					if(mipWidth<1){
						mipWidth=1;
						blockWidth=4;
					}
					tempSize=blockHeight*blockWidth;
					if(tempSize<16)
						tempSize=16;
					size+=tempSize;
					 if (mipHeight==1 && mipWidth==1) break;//A full MIP map chain ends with the 1x1 texel texture inclusive
				}
			}
			return size;
		
		
		case DXT1:
			size=(width*height)/2;
			mipWidth=width;
			mipHeight=height;
			
			
			if(mipMaps!=0){
				for(int i=0;i<mipMaps;i++){
					mipWidth=mipWidth/2;
					mipHeight=mipHeight/2;
					blockWidth=mipWidth;
					blockHeight=mipHeight;
					if(mipHeight<1){
						mipHeight=1;
						blockHeight=4;
					}
					if(mipWidth<1){
						mipWidth=1;
						blockWidth=4;
					}
					tempSize=(blockHeight*blockWidth)/2;
					if(tempSize<8)
						tempSize=8;
					size+=tempSize;
					 if (mipHeight==1 && mipWidth==1) break;//A full MIP map chain ends with the 1x1 texel texture inclusive
				}
			}
			return size;
		
		case ABGR8:
			size=width*height*4;
			mipWidth=width;
			mipHeight=height;
			
			if(mipMaps!=0){
				for(int i=0;i<mipMaps;i++){
					mipWidth/=2;
					mipHeight/=2;
					if(mipHeight<1)
						mipHeight=1;
					if(mipWidth<1)
						mipWidth=1;
					tempSize=mipWidth*mipHeight*4;
					size+=tempSize;
					 if (mipHeight==1 && mipWidth==1) break;//A full MIP map chain ends with the 1x1 texel texture inclusive
				}
			}
			return size;
		
		case Luminance8:
			size=width*height;
			mipHeight=height;
			mipWidth=width;
			
			if(mipMaps!=0){
				for(int i=0;i< mipMaps;i++){
				mipWidth/=2;
				mipHeight/=2;
				if(mipHeight<1)
					mipHeight=1;
				if(mipWidth<1)
					mipWidth=1;
				tempSize=mipHeight*mipWidth;
				size+=tempSize;
				 if (mipHeight==1 && mipWidth==1) break;//A full MIP map chain ends with the 1x1 texel texture inclusive
				}
			}
			return size;

The code snippet above seems me correct (although I would take advantage of the similarity of all 5 calculations and make a parametrizable solution from them; and those additional checks that tempSize has a minimum value seems me not necessary).

Yes you are right the checks for tempSize is not necessary

What are you using the routine for?
If it's for measuring how much VRAM you're using, then it's only a lower-bound estimate due to pitch/padding ;)

This topic is closed to new replies.

Advertisement