Understanding endInvocationInterlockARB in GLSL

This article explains the purpose and behavior of the endInvocationInterlockARB function within OpenGL's GL_ARB_fragment_shader_interlock extension. It covers how this built-in GLSL function completes a synchronized critical section, releases hardware execution locks, and optimizes fragment shader throughput during operations like custom blending and order-independent transparency.

In modern GPU rendering, fragments covering the exact same pixel or sample location execute concurrently by default. This concurrency causes race conditions when reading from, modifying, and writing back to memory buffers or custom framebuffers. The GL_ARB_fragment_shader_interlock extension introduces critical sections to resolve these hazards, and endInvocationInterlockARB serves as the explicit boundary that closes this synchronized execution zone.

The primary function of endInvocationInterlockARB is to release the per-pixel or per-sample mutual exclusion lock acquired earlier in the shader by beginInvocationInterlockARB. Once a fragment shader invocation executes endInvocationInterlockARB, it notifies the GPU hardware that it has finished its serialized operations. This action allows the next waiting fragment invocation that maps to the same screen-space coordinates to enter the critical section and execute its own synchronized instructions.

Calling endInvocationInterlockARB transitions the invocation back to regular parallel execution. Any instructions placed after this call run concurrently with other invocations without ordering guarantees. This design is critical for GPU performance. Serializing code reduces GPU parallelism, so developers should keep the block between beginInvocationInterlockARB and endInvocationInterlockARB as brief as possible, containing only the dependent read-modify-write logic. Any heavy mathematical calculations, lighting evaluations, or texture fetches that do not depend on the shared state should be kept outside these boundaries.

GLSL enforces strict control flow requirements regarding the placement of endInvocationInterlockARB. A shader invocation must execute endInvocationInterlockARB at most once, and only after beginInvocationInterlockARB has already been executed within the same dynamic control path. Calling it inside non-uniform conditional branches or loops that cause divergence between invocations can lead to undefined behavior or hardware deadlocks.