I am attempting to add a custom full-screen post-processing effect, a simple outline around opaque objects based on sampling the scene depth. Nothing crazy, except that it must be rendered before transluscent objects and fog, so that the outlines are fogged with all the opaque objects and don’t render over particles and other transluscent things. This means the easy way of using a PostProcessMaterial won’t work, as these only function after all opaque and transluscent rendering have finished.
I’m also trying to do this without modifying any engine code (though this is not a hard requirement), and the ‘sanctioned’ way seems to be to use a SceneViewExtension. It’s a simple edge detection based on depth, for which I need access to the depth buffer, and eventually read/write access to the scene color render target.
The catch here is that I need this to work on mobile, using the mobile forward renderer. I have something currently that is working perfectly fine in the editor, when previewing in Android Vulkan mode. However, on device I hit an ensure that seems related to some unexpected issue with the scene textures’ usage in the shader, and although the shader still runs, any sampling of the depth buffer seems to just gives me back 0s. (that said, returning a flat color, for example, produces the expected result, so I know at least writing back out to the render target is working just fine)
I’m almost certain the issue is either:
- The depth buffer is not actually available at this point in the render pipeline.
- My cpp code that sets up the shader parameters isn’t correct.
Hopefully it’s the latter - there’s very little documentation for SceneViewExtensions, and pretty much nothing if you’re trying to use any of the callbacks besides PrePostProcessPass_RenderThread. The callback I’m using doesn’t give me an FRDGBuilder or a direct reference to the SceneTextures, so it’s been a good bit of trial and error just to get anything working at all with just the FRHICmdList and FSceneView.
One thing I’ve noticed is that the `RenderForwardMultiPass` path is taken by the mobile forward renderer when simulating in the editor. On my test Android device, which is running Vulkan, the renderer takes the `RenderForwardSinglePass` path instead, shown below.
If I remove the SceneDepth parameter and just return a solid color, or a color defined by simple scalar / vector parameters I pass in, then everything works just fine. I’ve also noticed that if I send SceneColor, it comes up black, but I assume this is because I can’t read/write it in the same render pass and need to do a copy into a new render target first (though again, for some reason it works just fine in the editor when simulating).
Attached are some stripped-down versions of the relevant scene view extension and shader code. Hopefully I’m missing something very simple here.
`// FMobileSceneRenderer::RenderForwardSinglePass, in MobileShadingRenderer.cpp
// …
// Depth pre-pass
RHICmdList.SetCurrentStat(GET_STATID(STAT_CLM_MobilePrePass));
RenderMaskedPrePass(RHICmdList, View);
// Opaque and masked
RHICmdList.SetCurrentStat(GET_STATID(STAT_CLMM_Opaque));
RenderMobileBasePass(RHICmdList, View, &PassParameters->InstanceCullingDrawParams);
RenderMobileDebugView(RHICmdList, View);
RHICmdList.PollOcclusionQueries();
PostRenderBasePass(RHICmdList, View); // <— My scene view extension gets called in here
// … render decals, transluscent, fog
// Ensure I’m hitting when running on-device:
04-14 15:23:51.278 22679 22912 D UE : [2025.04.14-20.23.51:278][ 0]LogOutputDevice: Error: Ensure condition failed: Layout == VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL || Layout == VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR || Layout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL || Layout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL || Layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL || Layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL || Layout == VK_IMAGE_LAYOUT_GENERAL [File:Runtime/VulkanRHI/Private/VulkanDescriptorSets.h] [Line: 1084]`