Quick answer: Insert RHICmdList.Transition(FRHITransitionInfo(Texture, FromState, ToState)) before binding a texture in a new state. Validation layer messages name the texture and required state.

A custom post-process pass in Unreal’s renderer triggers Vulkan validation errors: VUID-vkCmdDrawIndexed: image layout VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL doesn’t match expected layout. Layout transitions missed.

Diagnose with Validation Layer

UE5Game.exe -vulkanvalidation

Console window shows validation messages with full call stack into the RHI. Look for the texture name and required state.

Insert Transition

RHICmdList.Transition(FRHITransitionInfo(SceneColor, ERHIAccess::RTV, ERHIAccess::SRVCompute));
// now safe to bind as compute SRV
SetUAVParameter(...);
RHICmdList.DispatchComputeShader(...);

Transitions are required between any pair of incompatible accesses: RTV ↔ SRV, UAV ↔ SRV, etc.

Common Patterns

FromToWhen
RTVSRVafter render-to-texture, read in next pass
UAVComputeSRVcompute writes, fragment reads
CopySrcCopyDestchained copies
PresentRTVback-buffer at frame start

RDG to the Rescue

Unreal’s Render Dependency Graph (RDG) auto-inserts transitions. Migrate custom passes from RHI to RDG:

GraphBuilder.AddPass(...);   // RDG handles transitions

For performance-critical passes, RDG’s overhead is negligible and the safety win is large.

Verify with RenderDoc

RenderDoc capture; inspect resource states in the Pipeline State panel. Each texture binding shows expected vs actual state. Mismatch is highlighted.

Verifying

Re-run with validation. No image layout errors. RenderDoc shows clean state transitions per draw. Visual output unchanged.

“Vulkan barriers are explicit. Either transition manually before each cross-state use, or let RDG do it for you.”

For console targets (Xbox / PS5), the lower-level GNM/D3D12 APIs have similar transition concepts — RDG normalizes across all RHIs.