How the GLSL FILE Macro Identifies Source Strings
The __FILE__ macro in the OpenGL Shading Language (GLSL)
preprocessor uniquely identifies shader source segments by expanding to
a decimal integer constant rather than a text filename. Because the
OpenGL API allows shaders to be assembled from an array of separate text
strings, the preprocessor uses this integer to represent the zero-based
index of the specific source string currently being parsed. This
mechanism allows developers and compilers to trace compile-time errors
and warnings back to their exact source origin within multi-part
shaders.
Integer Evaluation Instead of String Literals
In standard C and C++, the __FILE__ macro expands to a
string literal containing the name or path of the current source file
(e.g., "main.cpp"). In GLSL, string literals are largely
unsupported by the core language and its preprocessor. Consequently, the
GLSL specification defines __FILE__ as a decimal integer
indicating the source string number.
Mapping to
glShaderSource
When passing source code to the GPU via the OpenGL API, developers
typically use the glShaderSource function:
void glShaderSource(GLuint shader, GLsizei count, const GLchar **string, const GLint *length);The count parameter specifies the number of individual
strings contained in the string pointer array. The GLSL
preprocessor sequentially compiles these strings as a single compilation
unit, assigning an automatic index to each:
- The first string in the array (index
0) has__FILE__evaluated to0. - The second string in the array (index
1) has__FILE__evaluated to1. - Subsequent strings increment this value sequentially
(
2,3, ...,count - 1).
If a syntax or compilation error occurs, the shader compiler
references this value in its error log, typically formatting diagnostic
messages as 0(15) : error ... or
ERROR: 0:15: ..., where the first number corresponds to the
__FILE__ index and the second corresponds to the
__LINE__ number.
Manipulating
__FILE__ with the #line Directive
The behavior of __FILE__ can be manually overridden
using the #line preprocessor directive. GLSL supports an
extended syntax for this directive:
#line line_number
#line line_number source_string_numberWhen provided with two arguments, the directive sets
__LINE__ to line_number and
__FILE__ to source_string_number. Both
arguments must be integral expressions.
This capability is commonly used by asset pipelines, pre-compilers,
and custom #include implementations. When a preprocessor
dynamically injects header files or external code into a shader string,
it can insert a #line [line] [file_id] directive before and
after the injected content. This ensures that any compiler diagnostics
report the custom file ID assigned to that header rather than the linear
array index passed to the graphics driver.