GLSL LINE Macro: Definition and Usage

The __LINE__ predefined macro in the OpenGL Shading Language (GLSL) is a preprocessor directive that provides the current source code line number as an integer during shader compilation. This article explains the technical behavior of __LINE__, how it changes during the compilation process, how developers can modify its value using the #line directive, and its practical applications in debugging and shader development pipelines.

What Information Does __LINE__ Provide?

In GLSL, __LINE__ always expands to a decimal integer constant representing the current line number within the shader source string currently being processed. When the shader preprocessor encounters the __LINE__ token, it replaces it with the line number where that token resides.

Line numbering starts at 1 for the first line of the source code and increments by one with each subsequent newline character encountered during processing.

How __LINE__ Works During Compilation

Shader compilation in OpenGL occurs in stages, beginning with preprocessing. Because __LINE__ is resolved by the preprocessor:

  • Static Replacement: It is replaced by an integer literal before syntactic and semantic analysis take place. The GPU execution unit never evaluates __LINE__ dynamically; its value is fixed at compile time.
  • Scope Across Multi-String Sources: When shaders are supplied via multiple source strings (for instance, through the glShaderSource API call), the line count continues sequentially unless modified. However, GLSL also tracks the source string index via the __FILE__ macro, which is an integer identifying which source string contains the current code.

Modifying __LINE__ with the #line Directive

The behavior of __LINE__ can be manually altered using the #line directive. This allows developers or build tools to override the internal line counter:

#line 100
// The next line will evaluate __LINE__ as 100

GLSL supports two forms of the directive:

  1. #line line_number sets the line number for the subsequent line to line_number.
  2. #line line_number source_string_number sets both the line number and the source string index (which modifies __FILE__).

This directive does not alter the actual line count of the physical file; it only overrides what the compiler and preprocessor report for diagnostics and __LINE__ expansion.

Common Practical Applications

1. Mapping Generated Code to Original Files

In modern graphics engines, shaders are often constructed by concatenating modular files, preambles, and generated template code. If an error occurs, the compiler's line reporting points to the combined file rather than the original source. By injecting #line directives matching the original source locations, build systems ensure that __LINE__ accurately reflects the line of the original author's file.

2. Custom Debugging and Assertions

Developers frequently use __LINE__ alongside custom macros to build diagnostic utilities or assertion handlers in GLSL:

#define ASSERT_VALID(condition) \
    if (!(condition)) { /* Logic encoding __LINE__ into visual output */ }

3. Error Tracking in Shader Translators

Tools that transpile high-level shading languages (such as HLSL or Slang) into GLSL rely on __LINE__ to maintain precise correlation between the target GLSL lines and the source language lines during compiler diagnostics.