1
\$\begingroup\$

Firstly I am in Unity 2021.3.11f1 using DX12.

So the situation is the following. I have a large 3D RenderTexture, and I have a large 3D Texture3D with the same data, same format, same dimensions, same size in memory, as the RenderTexture.

Now I have a compute shader that samples from these many times (volume rendering).

  • If I use the Texture3D, the compute shader takes 50ms to run in total.
  • If I use the RenderTexture instead, changing nothing else, the compute shader takes 170ms to run in total.

Why does this happen? It also happens with large 2D textures as well.

I would just say whatever and use the Texture2D/3D, but the problem with that is that not only does it take a lot longer to create a new large Texture2D/3D, it creates large lag spikes when I need to copy from the RenderTexture to the Texture2D (I use another compute shader to write the data to the texture), which is a big problem because in the case of the 2D Texture/Rendertexture that gets recreated frequently (dynamic atlas).

What can I do and why is this happening in the first place?.

Code if I want to use a rendertexture:

RenderTexture TempVolumeTex = new RenderTexture((int)OrigionalSize.x, (int)OrigionalSize.y, 0, RenderTextureFormat.RFloat, RenderTextureReadWrite.sRGB);
TempVolumeTex.enableRandomWrite = true;
TempVolumeTex.volumeDepth = (int)OrigionalSize.z;
TempVolumeTex.dimension = UnityEngine.Rendering.TextureDimension.Tex3D;
TempVolumeTex.Create();
VolumeShader.SetTexture(1, "DDATextureWrite", TempVolumeTex);
VolumeShader.Dispatch(1, Mathf.CeilToInt(OrigionalSize.x / 8.0f), Mathf.CeilToInt(OrigionalSize.y / 8.0f), Mathf.CeilToInt(OrigionalSize.z / 8.0f));

and if I want to use a texture3d, I still have to do the exact same as above, but then I have to do:

VolumeTex = new Texture3D((int)OrigionalSize.x, (int)OrigionalSize.y, (int)OrigionalSize.z, TextureFormat.RFloat, false);
Graphics.CopyTexture(TempVolumeTex, VolumeTex);

Top is using a texture3d, bottom is using a rendertexture, with their respective dimensions and memory size being in the bottom right

\$\endgroup\$
0

1 Answer 1

1
\$\begingroup\$

I can think of three possible causes of this:

  1. The RenderTexture will be bigger in memory because it's not compressed. This will consume more memory bandwidth on the GPU to sample, and is also likely to cache miss more often.
  2. The RenderTexture probably won't have mip maps. Those can improve performance significantly if you make use of them when sampling the texture.
  3. The RenderTexture might well be swizzled / tiled in a way that's good for writing to, but not as cache friendly for reading from.

To improve performance I'd suggest:

  1. Optimize the format of the render texture to minimize the number of bytes per pixel that it uses (an 8bpp texture should be faster than 128bpp).
  2. You could add mip maps to the RenderTexture, but that would require extra work to generate them between writes to and reads from the texture.
  3. If the writes to the RenderTexture are infrequent, then it's possible to use a compute shader to compress the texture after writing to it, but doing so is going to be quite expensive.
\$\endgroup\$
1
  • \$\begingroup\$ the size in memory of the rendertexture and texture3d are the same in memory acccording to unity, and I have them as small as I can, for the 3d scenario they are float32's The swizzled thats good for writing to but awful for reading from makes sense, but its such a shame if thats the case, as that means theres not much that can be done... \$\endgroup\$
    – Pjbomb2
    Jan 20, 2023 at 19:45

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .