For an OXR app running on Quest3 I would like to add a full screen effect (with framebuffer fetch) after rendering opaque objects.
Following the example from the manual and the RP samples assets I am able to create a new RenderPass/RenderFeature. However, this pass needs “requiresIntermediateTexture=true” to be set. This pretty much defeats the purpose since I am now adding an extra copy/resolve step instead of saving time by reading data back directly from the fast GMEM. Is there a workaround for this? Is it a Vulkan limitation?
According to ARM documents it looks like this should be possible on Vulkan & GLES:
Hi ![]()
This is a current limitation that we can not easily overcome with the current setup. The main reason is how y-flip is handled inside the engine, and when using post processing we have to flip the image at the end which does prevent us from staying fully on tile. Without post processing we can directly render to the eye texture (back buffer).
This is currently a high priority for us to unlock fully on-tile post processing, specifically for untethered XR, but we are currently investigating the best solution for that. So you can be sure we do our best to overcome this limitation in the near future, but right now it is not possible.
What effect do you want to achieve? A lot of studios are working around this issue by integrating some of the effects like Color Grading into the material.
This is similar to “when is it good to plant a tree?” question, you know…
The best time to remove that stupid y-flip was 10 years ago (back when whole SRP thing got started). The second best time is now.
The only reason why it exists in the first place, is because Unity started out as an OpenGL-only engine, back when framebuffer objects did not exist, and then all the later API/platform additions tried to keep the behavior the same. But, as everyone has noticed, this is a very high tax, that keeps on hitting people in unexpected places, and besides that “backwards compatibility with Unity 1.x”, has no technical reason to exist anymore.
Are graphics people at Unity looking to remove that upside-down flip thing at some point? It would be very, very appreciated.
Yes I fully agree with that and we are actively looking into how we can finally get rid of y-flip, even if upgradability of projects is still very important to us.
If we would just assume now that we would flip only if UV starts NOT at the top in the new world, we might add an additional flip to very low end devices (e.g. we still support GLES 3.0, and now support WebGL on mobile), and might regress performance there.
But the advantage would be that we totally remove unnecessary blit on 80% of APIs. The industry is moving to Vulkan and WebGPU, and we are pushing as well, but we still need to consider it carefully.
I was under impression that at least some of these cases, when needed, can also be addressed without a performance hit. E.g. there’s EXT_clip_control extension that seems to be widely supported on WebGL, and supported by some OpenGL ES devices too. Or, on the engine side, the engine could do the “final upside down flip”, when needed, only in the very final blit it does. So the whole thing would be isolated into one place, instead of everyone having to think about it all the time.
Yes, these are all factors we’re considering, and we’re actively working on a solution. Balancing compatibility, performance, and resource constraints makes it a complex challenge, but it’s a priority for us.
Thank you Oliver. I had tried running the framebuffer fetch example on the Quest3 device and ended up with framebuffer corruption; before spending too much time debugging I wanted to double check whether backbuffer read&writes are supposed to work or not.
At 34:28 your speaker at this GDC talk says that this is a limitation of desktop rendering and should work on mobile. You are saying that is not the case right now.
Hey @grubert_unity, I’m the speaker you mentioned above.
I had tried running the framebuffer fetch example on the Quest3 device and ended up with framebuffer corruption; before spending too much time debugging I wanted to double check whether backbuffer read&writes are supposed to work or not.
I think it is possible to use framebuffer fetch with the backbuffer on Quest3, but I haven’t tried it. Although, we did talk to an external team a year ago which was doing something similar to my GDC demo on Quest 2. They were copying the backbuffer to a temporary on-tile texture in their first RG pass through fbf (1st subpass), then applying their effect using this temporary texture as input back to the backbuffer through a second fbf in their second RG pass (2nd subpass). They didn’t mention any rendering issues.
your speaker at this GDC talk says that this is a limitation of desktop rendering
We always force a final blit in the Editor, so we can’t render directly to the “backbuffer” hence the limitation.
What kind of corruption do you have? Also, I’m not sure requiresIntermediateTexture = true; is really necessary here. It might be for some plaftorms/gfx APIs, but I would probably try without on Quest 3 and see how it goes.
Thanks for the clarification @amoulin
I can’t share too many details, but here is a screengrab from RenderDoc. When running the fbf sample in the editor I see the framebuffer tinted blue as expected. On Quest3, not so much:
Yes, very much so, it’s a very active topic right now. You’re welcome to help us remove it ![]()
It’s probably not needed indeed, and overly conservative as an example. However, this has barely been used so hitting a bug is likely.
It doesn’t work. It gives null at the time of execution: How to Import color backbuffer to read on Meta Quest 3 + Vulkan
Any time lines on when this will be possible? Rendering via intermediate textures is quite a hit on TBRs.
It’s possible in 6.3.
Before, a memoryless resource doesn’t have an RTHandle, so any conversion from TextureHandle to RTHandle in the RG Execution stage will fail. You could hack the error throwing because it’s not really needed. The main case is to check the flippness/UVorientation but you can work around that.
For 6.4, we are working on On-Tile Post Processing for Quest. Here we do also want the intermediate textures, but memoryless. The complexity here is that all textures in Unity have a BottomLeft UV orientation (UV 0,0 is BottomLeft), while Vulkan uses TopLeft. Therefor, there is a flip required that breaks the pass. But we found a solution to work around that. More on that soon.
Does anyone know how I would do this in a custom SRP using Unity 6.2? I’m not using SRP rendergraph or anything else from the SRP Core Library, but I am using Vulkan with native render passes on an XR device. (Quest 2/3)
I tried setting the same color buffer as both a framebuffer input and output for the same render pass, but that gave me an error, so I assume another approach is required.
I need to use this to render water correctly with the object behind it. Ideally I would use dual source blending, but Unity doesn’t expose this. Currently I have to do two passes which isn’t ideal.

