Jump to content
  • Advertisement
Sign in to follow this  
Mr_Fox

Benefits of use Texture2D<uint/int> 16bit over Texture2D<float> 16bit

This topic is 616 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hey Guys,

 

I have a pass which will generate depth data in a Texture2D. Before, I decide to keep Depth Cam default format "Texture2D<short> " which is effective 16bit uint with each pixel store it's z value in mm. However, in a later path which I wish to do a 2x2 smooth I suddenly realized that I cannot do linear sample over integer texture.  Converting this 16bit uint texture into 16bit float is trivial (I am doing it right now)  But what benefits we get for having a integer texture2d over the float version which all have same bit precision?  You lose built-in HW for cheap interpolation, in return just to get uniform precision along the range?

 

In my case I will have pixel value around 1.f - 100.f, so precision from 16bit integer doesn't seems to be an attractive benefit, so what good thing I got for int over float? Only atomic ops? (and that's only for 32bit right?) (maybe integer inst are cheaper? I heard integer divide is even more expensive than float version though...)

 

In general what you guys use Texture2D<uint/int> for? (especially 16bit ones which can't do atomic ops, and have float available for those bits)

 

Thanks

Share this post


Link to post
Share on other sites
Advertisement

If you're after uniform precision and the ability to bilinearly sample the texture then you should really be creating a texture in the format R16_UNORM and scaling your input/output according to the range you're after.

 

If the pixel values are in the range 1.0f to 100.0f, then simply multiply by 100.0f on read and multiply by 0.01f on write. R16_UNORM textures should be declared as Texture2D<float> in the shader. The use of the word "float" here doesn't denote that the underlying format is necessarily a floating point format (R16_UNORM isn't) but that the data is returned to you as a floating point value in the shader.

 

Having an integer formatted texture when you're dealing with integer data makes sense and avoids the need to continually cast/convert between float/uint as well as rescale the data on read/write.

 

What you said about atomic ops is true (32 bit only) and integer division is often slow, but that doesn't mean there aren't good reasons to use integer formatted textures. Stencil is an 8bit UINT texture after all. If what you want to store is a set of flags, an ID, a count or an index, it makes little sense to use anything other than an integer format of the smallest bit depth suitable.

Edited by Adam Miles

Share this post


Link to post
Share on other sites

If you're after uniform precision and the ability to bilinearly sample the texture then you should really be creating a texture in the format R16_UNORM and scaling your input/output according to the range you're after.

 

Thanks Adam, I think I will use UNORM instead in my project. But I was wondering is there any way to 'control' the HW interpolation?  For example, when I do interpolation among 4 neighboring pixels, the interpolation result only make sense if all 4 pixel are valid, but it possible that such 2x2 pixels contain invalid data (like 0 for instance). 

 

Since my pixel value range is (0, 1) how could I set invalid value such that I can easily tell whether a interpolated sample contain invalid data?

 

Can I set pixel value to nan in R16_UNORM?

 

What SampleLevel will return if one of its 2x2 pixels is nan?

 

Thanks

Share this post


Link to post
Share on other sites

There's no way to exclude a particular texel from a sample, no.

 

If zero means something special to you then I would suggest using "GatherRed" to return all 4 texels in a 2x2 area to the shader in a single fetch. I believe they're ordered counter-clockwise where .x = lower left corner. From there you can do your own bilinear filtering and exclude one or more of the samples and reweigh the valid ones.

 

R16_UNORM doesn't support NaN since all 65,536 bit patterns represent a valid fraction between 0.0f and 1.0f.

 

If the format you were reading from did support NaN, then any NaNs in the sample operation would mean the returned value was NaN.

Share this post


Link to post
Share on other sites

If zero means something special to you then I would suggest using "GatherRed" to return all 4 texels in a 2x2 area to the shader in a single fetch. I believe they're ordered counter-clockwise where .x = lower left corner. From there you can do your own bilinear filtering and exclude one or more of the samples and reweigh the valid ones.

 

But if I do Gather and then interpolate in shader thus the perf will be almost the same as the R16_UINT version I guess?  or Gather will be faster than 4 neightboring Load? And if yes, why Gather will be faster since they all touch four pixels?

 

Thanks

Share this post


Link to post
Share on other sites

Gather has the same cost as one bilinear sample, which is roughly 1/4 the cost of doing 4 individual loads. Gather isn't available for integer formatted textures (although I will fight the good fight until it is!).

 

Bilinear filtering is free on most hardware for 1, 2 and 4 byte per pixel formats even though it also touches four texels. Gather is free for the same reason.

Edited by Adam Miles

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!