create texture3D

Started by
12 comments, last by YixunLiu 7 years, 1 month ago

Hi,

I would like to load a 3D image with pixel format: short and create a texture3D.

Some example use structureBuffer. Which resource is more efficient?

I need to do volume rendering and slicing.

I think texture3D is more efficient due to its hardware support for interpolation, but I am not sure if I can create texture3D for short format.

Thanks.

YL

Advertisement

A 2-byte-per-pixel Texture3D is fine.

Adam Miles - Principal Software Development Engineer - Microsoft Xbox Advanced Technology Group

Got it.

Thanks.

You can create a texture with DXGI_FORMAT_R16_SINT, which is equivalent to the "short/int16_t" type in C++ when running on Windows (there's also R16_UINT which is equivalent to "unsigned short/uint16_t"). You can see which formats are available for various use cases by checking the DXGI documentation for the feature level that you're targeting. For instance, here's the list of format support for D3D_FEATURE_LEVEL_11_0. If you check that list, you'll see that 3D texture support for R16_SINT and R16_UINT are both required for FEATURE_LEVEL_11_0. However if you check the support for Sample with texture filtering (interpolation), you'll see that none of the SINT or UINT formats are supported. So you wouldn't be able to get hardware interpolation if you want to deal with raw integers. However if you're okay with having your integers be interpreted as a [0, 1] or [-1, 1] floating point number, then you can use the equivalent UNORM or SNORM formats. These have support for filtering, so you could use hardware interpolation. You can also use filtering with FLOAT formats if you need to go beyond [-1, 1] range.

Buffer resources are generally going to be optimized for linear access patterns. So if you you have 1024 consecutive threads that each load from the buffer using their thread ID (e.g. thread 0 loads element 0, thread 1 loads element 1, thread 32 loads element 32, etc.) then a buffer is a good choice. Textures are optimized for 2D locality. So if you have 64 threads that access an 8x8 block of texels from a texture, then a texture is a good choice since it will probably be swizzled to match that sort of access pattern. If you need filtering then textures are also a good choice, since in many cases a 2x2 bilinear sample is the same cost as a single point sample or Load(). 3D textures may be optimized for 3D locality, but it depends on the hardware. Some hardware may internally store the 3D texture as N 2D slices, in which case texels from adjacent Z slices won't be adjacent in memory.

As always, if you really want to know for sure which is faster you will need to profile it.

If you are doing raycasting kinda volume rendering, use Texture3D rather than StructuredBuffer for it's smooth perf from different point of view. Have a look at my old post about that. Texture3D memory layout follows a Morton pattern so the overall cache hit rate should be better than StructuredBuffer linear memory layout (think about casting a ray in z axis, neighbor pixel are one slice away from each other...)

If I use DXGI_FORMAT_R16_SINT for Textture3D, as MJP said, the filter is not supported. Do I need to create a sampler?

If yes, how to fill D3D11_SAMPLER_DESC? Especially for D3D11_FILTER part?

I do not want to use FLOAT since it will double my memory. If use SNORM, I need additional scaling operation. Maybe need to use a constant buffer to store the max value for scaling back. If use R16_SINT, I lose hardware interpolation. StructuredBuffer is not good as Mr_Fox said. What's your suggestion? I want to do volume rendering and slicing.

Thank you so much.

MJP explained your options quite well.

If I use DXGI_FORMAT_R16_SINT for Textture3D, as MJP said, the filter is not supported. Do I need to create a sampler?

You can't sample integer formatted textures, so no, don't create a sampler. You can only 'Load' or use the [] operator to fetch a single texel at a time.

If hardware interpolation is important to you then you will have to use Texture3D + R16_SNORM and perform a scaling operation. If you know what the scale is at compile time just hardcode the scale rather than load it from a constant buffer, it may save you a bit of performance.

Adam Miles - Principal Software Development Engineer - Microsoft Xbox Advanced Technology Group

There's also R16_FLOAT, which implies half-precision floating point values.

Thank you so much for all your answers!

Thanks for your guys reply.

I still have two questions.

1. Based on what you said, I plan to use DXGI_FORMAT_R16_SINT when I create texture3D using CreateTexture3D().

Now my question is, when I crate SRV, I have to specify the format in CD3D11_SHADER_RESOURCE_VIEW_DESC.

Still use format DXGI_FORMAT_R16_SINT? If I use DXGI_FORMAT_R16_SINT in SRV, how to specify texture3D in HLSL?

I think it should be Texture3D<short> texture: t0, but I cannot find short type support from HLSL reference:

https://msdn.microsoft.com/en-us/library/windows/desktop/bb509646(v=vs.85).aspx

2 My second question is from MJP said, I need to check the texture support and filter support based on the format I want to use. Since I need to specify format as I create texture and SRV and these two formats might be different. I want to know which format should I use to check the support.

Thanks a lot!

This topic is closed to new replies.

Advertisement