Jump to content

  • Log In with Google      Sign In   
  • Create Account

We're offering banner ads on our site from just $5!

1. Details HERE. 2. GDNet+ Subscriptions HERE. 3. Ad upload HERE.


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


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
7 replies to this topic

#1 jor1980   Members   -  Reputation: 142

Like
0Likes
Like

Posted 20 April 2014 - 11:13 AM

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;
				}
			}


Sponsor:

#2 haegarr   Crossbones+   -  Reputation: 4437

Like
1Likes
Like

Posted 20 April 2014 - 02:17 PM

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.

Edited by haegarr, 21 April 2014 - 06:41 AM.


#3 jor1980   Members   -  Reputation: 142

Like
0Likes
Like

Posted 21 April 2014 - 03:14 AM

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



#4 haegarr   Crossbones+   -  Reputation: 4437

Like
1Likes
Like

Posted 21 April 2014 - 04:16 AM


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).



#5 jor1980   Members   -  Reputation: 142

Like
0Likes
Like

Posted 22 April 2014 - 08:34 AM

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;


#6 haegarr   Crossbones+   -  Reputation: 4437

Like
0Likes
Like

Posted 22 April 2014 - 10:40 AM

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).



#7 jor1980   Members   -  Reputation: 142

Like
0Likes
Like

Posted 22 April 2014 - 03:07 PM

Yes you are right the checks for tempSize is not necessary



#8 Hodgman   Moderators   -  Reputation: 31131

Like
0Likes
Like

Posted 22 April 2014 - 04:29 PM

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 ;)




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS