Search Unity

Reading Depth

Discussion in 'Shaders' started by DavidSWu, Jan 12, 2020.

  1. DavidSWu

    DavidSWu

    Joined:
    Jun 20, 2016
    Posts:
    183
    We would like to read the depth of the last opaque pixel drawn during transparency rendering efficiently on Mobile GPU's running GLES 3.0+, Metal and Vulkan.
    It seems that most of them have support for this built-in but it is not entirely clear what the more efficient way to go about doing it with Unity is.
    We use MSAA4x which complicates things somewhat, (i.e. there are 4 depth values per pixel - we would be happy with one, an averaged value, all 4 samples whatever).
    The current URP does an extra pass if you ask for camera depth and you have MSAA on. This is not acceptable to us performance-wise.
    We modified the RP to resolve the depth buffer and then MSAA sample it down to a readable texture but this is expensive, partly because we have to resolve the whole MSAA4X buffer to memory and access every sample in a shader which is a lot of memory.
    There are ARM GLSL extensions, but this seems like a last resort (which we will try if there is not a nicer solution)
    The RenderPass API seems like an option, but the documentation says that depth buffer read access is not supported on Metal. I am not sure if this is up to date.

    Any help or suggestions would be greatly appreciated.
     
  2. neoshaman

    neoshaman

    Joined:
    Feb 11, 2011
    Posts:
    6,493
    Sound like a tile based optimization issue, it's inevitable you would use memoryless blending.
     
  3. DavidSWu

    DavidSWu

    Joined:
    Jun 20, 2016
    Posts:
    183
    We set everything that we can to memoryless, and that helps.
    The main thing here is that there are very efficient ways to read the current depth of the pixel being drawn but we are unable to use this at present due to API limitations.
    There may also be issues with hardware or driver support. For example, the RenderPass API should work on Vulkan, but Vulkan doesn't always work that well in general (I still have my hopes up for this one day :) ).
    It might be "good" enough to resolve to memory if we could auto-resolve depth without having to copy the whole MSAA depth buffer to memory and then sample all of that from a shader, draw it back to tiled memory and resolve it again.
    But then again, it may be that copying from tiled memory to GPU memory is fast enough (i.e. if it happened in parallel, who knows, maybe tiles are double buffered so that you can export to memory while rendering the next tile. That would make sense. Even if you are limited by bandwidth, reads and writes should have independent limits).
     
  4. neoshaman

    neoshaman

    Joined:
    Feb 11, 2011
    Posts:
    6,493
    What about outputting the fragment distance in shader?
     
  5. DavidSWu

    DavidSWu

    Joined:
    Jun 20, 2016
    Posts:
    183
    That is possible. We could use MRT. It feels redundant but it would work.
    Thanks for the suggestion!
     
    neoshaman likes this.