Search Unity

When is a rendertexture safe to read from?

Discussion in 'Shaders' started by cblarsen, May 22, 2008.

  1. cblarsen

    cblarsen

    Joined:
    Mar 10, 2007
    Posts:
    266
    A number of people have problems with my latest shader:
    http://forum.unity3d.com/viewtopic.php?t=11626

    The screenshots they are showing me look a bit like a problem I had earlier on myself, where I read from a rendertexture too soon.

    My algorithm goes something like this

    Inputs: Bumpmap/heightmap B
    Color/Specular map C
    "temp" rendertexture R

    Phase 0: Clear rendertexture R
    Phase 1: Trace bumpheightmap B - write result into rendertexture R
    Phase 2: Read results from R, and use B to refine results using binary search. Write results back to R (same pixel)
    Phase 3: More depth refinement. Reading from R, writing back to R
    Phase 4: Reading from R and B to calculate shadows. Write results back to R
    Phase 5: Finally render to screen, reading from R, B, and C

    Originally, I tried to have Phase 0,1, and 2 in one shader as several passes.
    However this gave errors of the type people are reporting now. Like this one posted by AngryAnt:
    http://www.getdropbox.com/gallery/18971/0/?h=61e159

    I solved it on my machine by having phase 1 and 2 as seperate shaders, drawn in two Render() calls to the same hidden camera. The problem was apparently that I was reading from the rendertexture before the last writes to it had completed.

    Is there a way to make sure rendering to a rendertexture has flushed completely?

    One of the cards with reported problems is the ATI X1600
    Similar, but not identical symptoms reported on X800
    Apparently the shaders are not detected as unsupported. I _think_ I am testing properly for that now.
     
  2. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    Normally passes should take care that you do not go to step 2 before step 1 is fully finished.
    I'm sadly not experienced enough yet with Unity Shaders to know if you are able to set passes manually / split them, instead of using distinct shaders.


    Old architectures are not highly parallel as the new ones are that are able to process 100-400 pixels in parallel, for that reasons old cards might not see it as they accessed the pixels "in order" or at least in enough order to not have a problem with it.
     
  3. cblarsen

    cblarsen

    Joined:
    Mar 10, 2007
    Posts:
    266
    I am sure they do, in the sense, that they make sure that the write operations to the destination happen in order, and wait if you are doing any blending.
    I already know of the possibility of calling material.SetPass() and Graphics.DrawMesh(), but I have no idea, if that will solve anything. And using DrawMesh() has limitations of its own.

    Well, my card is an X1900 XT, and it works here :|
     
  4. Aras

    Aras

    Unity Technologies

    Joined:
    Nov 7, 2005
    Posts:
    4,770
    Basically, it is never safe to read from a render texture while rendering into it. Everything else is okay. So your steps 2 to 4 are "unsafe".

    A workaround would be to use two textures and ping-pong between them. Step 2 reads from R1, writes into R2. Step 3 reads from R2 and writes into R1. And so on. That would be safe.
     
  5. cblarsen

    cblarsen

    Joined:
    Mar 10, 2007
    Posts:
    266
    I knew it! I just wouldn't admit it...

    Thanks Aras. It seems, that there are quite a few problems that can be solved by throwing texture memory at them :)