Difference between revisions of "Built-in Variable (GLSL)"

From OpenGL.org
Jump to: navigation, search
m (Vertex shader inputs)
m (Alfonse moved page GLSL Predefined Variables to Built-in Variable (GLSL): Better page name)
(31 intermediate revisions by 3 users not shown)
Line 1: Line 1:
 
The [[OpenGL Shading Language]] defines a number of special variables for the various shader stages. These '''predefined variables''' (or built-in variables) have special properties. They are usually for communicating with certain fixed-functionality. By convention, all predefined variables start with "gl_"; no user-defined variables may start with this.
 
The [[OpenGL Shading Language]] defines a number of special variables for the various shader stages. These '''predefined variables''' (or built-in variables) have special properties. They are usually for communicating with certain fixed-functionality. By convention, all predefined variables start with "gl_"; no user-defined variables may start with this.
 +
 +
{{note|This page only describes the core OpenGL shading language pre-defined variables. Any variables that are from the compatibility profiles are not listed here.}}
  
 
== Vertex shader inputs ==
 
== Vertex shader inputs ==
Line 6: Line 8:
  
 
<source lang="glsl">
 
<source lang="glsl">
in int gl_VertexID;
+
/* no inputs prior to GLSL 1.30 */
in int gl_InstanceID;
+
 
 +
in int gl_VertexID; /* GLSL ≥ 1.30 */
 +
in int gl_InstanceID; /* GLSL ≥ 1.40 */
 
</source>
 
</source>
  
Line 18: Line 22:
 
Vertex shaders have the following predefined outputs.
 
Vertex shaders have the following predefined outputs.
  
<source lang="cpp">
+
<source lang="glsl">
 
out gl_PerVertex
 
out gl_PerVertex
 
{
 
{
Line 27: Line 31:
 
</source>
 
</source>
  
This defines an [[GLSL Interface Blocks|interface block]] for outputs. The block is defined so that prefixing the names is not required.
+
''gl_PerVertex'' defines an [[GLSL Interface Blocks|interface block]] for outputs. The block is defined so that prefixing the names is not required.
  
 
''gl_Position'' is the output position of the current vertex (in clip-space, if there is no geometry shader). It is not necessary to write to this value in a vertex shader, though if you do not, don't be surprised if the primitives you get are not reasonable. You can reasonably omit writing to this variable if you are using transform feedback and shutting off rasterization, or if you are using a geometry shader that will use user-defined outputs to generate positions.
 
''gl_Position'' is the output position of the current vertex (in clip-space, if there is no geometry shader). It is not necessary to write to this value in a vertex shader, though if you do not, don't be surprised if the primitives you get are not reasonable. You can reasonably omit writing to this variable if you are using transform feedback and shutting off rasterization, or if you are using a geometry shader that will use user-defined outputs to generate positions.
Line 36: Line 40:
  
 
In order to use this variable, the user must manually redeclare it with a size.
 
In order to use this variable, the user must manually redeclare it with a size.
 +
 +
== Tessellation control shader inputs ==
 +
<source lang="glsl">
 +
/* no tessellation control shaders prior to GLSL 4.00 */
 +
 +
in gl_PerVertex
 +
{
 +
    vec4 gl_Position;
 +
    float gl_PointSize;
 +
    float gl_ClipDistance[];
 +
} gl_in[gl_MaxPatchVertices];
 +
 +
in int gl_PatchVerticesIn;
 +
in int gl_PrimitiveID;
 +
in int gl_InvocationID;
 +
</source>
 +
 +
== Tessellation control shader outputs ==
 +
<source lang="glsl">
 +
/* no tessellation control shaders prior to GLSL 4.00 */
 +
 +
out gl_PerVertex
 +
{
 +
    vec4 gl_Position;
 +
    float gl_PointSize;
 +
    float gl_ClipDistance[];
 +
} gl_out[];
 +
 +
patch out float gl_TessLevelOuter[4];
 +
patch out float gl_TessLevelInner[2];
 +
</source>
 +
 +
== Tessellation evaluation shader inputs ==
 +
<source lang="glsl">
 +
/* no tessellation evaluation shaders prior to GLSL 4.00 */
 +
 +
in gl_PerVertex
 +
{
 +
    vec4 gl_Position;
 +
    float gl_PointSize;
 +
    float gl_ClipDistance[];
 +
} gl_in[gl_MaxPatchVertices];
 +
 +
in int gl_PatchVerticesIn;
 +
in int gl_PrimitiveID;
 +
in vec3 gl_TessCoord;
 +
 +
patch in float gl_TessLevelOuter[4];
 +
patch in float gl_TessLevelInner[2];
 +
</source>
 +
 +
== Tessellation evaluation shader outputs ==
 +
<source lang="glsl">
 +
/* no tessellation evaluation shaders prior to GLSL 4.00 */
 +
 +
out gl_PerVertex
 +
{
 +
    vec4 gl_Position;
 +
    float gl_PointSize;
 +
    float gl_ClipDistance[];
 +
};
 +
</source>
  
 
== Geometry shader inputs ==
 
== Geometry shader inputs ==
  
<source lang="cpp">
+
<source lang="glsl">
 +
/* no geometry shaders prior to GLSL 1.50 */
 +
 
 
in gl_PerVertex
 
in gl_PerVertex
 
{
 
{
Line 50: Line 118:
 
</source>
 
</source>
  
The ''gl_PerVertex'' variables contain the values passed from the previous vertex shader stages. Note that in the geometry shader, they must be prefixed by ''gl_in'', which is an interface block array. The size of this array is based on the layout qualifier used for inputs for this geometry shader. You do not have to redeclare this block with a specific size; the system does this for you. As with any array, you can get its length with the ''length()'' function.
+
The ''gl_PerVertex'' variables contain the values passed from the previous shader stages. Note that in the geometry shader, they must be prefixed by ''gl_in'', which is an interface block array. The size of this array is based on the layout qualifier used for inputs for this geometry shader. You do not have to redeclare this block with a specific size; the system does this for you. As with any array, you can get its length with the ''length()'' function.
  
''gl_PrimitiveIDIn'' is the number of the current primitive being worked on during this rendering call. That is, the number of primitives previously processed by this ''glDraw*'' call.
+
''gl_PrimitiveIDIn'' is the number of the current primitive being worked on during this rendering call. It is the number of primitives previously processed by the current {{code|glDraw*}} rendering call.
  
 
GLSL 4.00 and above also have the following definitions:
 
GLSL 4.00 and above also have the following definitions:
  
<source lang="cpp">
+
<source lang="glsl">
 
in int gl_InvocationID;
 
in int gl_InvocationID;
 
</source>
 
</source>
  
Geometry shaders can be invoked multiple times; this value specifies the current invocation.
+
Geometry shaders can be invoked multiple times over the same primitive with [[Geometry_Shader#Instancing|geometry shader instancing]]; this value specifies the current invocation instance.
  
 
== Geometry shader outputs ==
 
== Geometry shader outputs ==
  
<source lang="cpp">
+
<source lang="glsl">
 +
/* no geometry shaders prior to GLSL 1.50 */
 +
 
 
out gl_PerVertex
 
out gl_PerVertex
 
{
 
{
Line 86: Line 156:
 
The ''gl_Layer'' variable is assigned to each vertex. If different vertices of a primitive get a different layer value, then OpenGL states that which layer is rendered to is undefined. Therefore, you should set it for each vertex emitted, and the value for each vertex of the same primitive should be the same.
 
The ''gl_Layer'' variable is assigned to each vertex. If different vertices of a primitive get a different layer value, then OpenGL states that which layer is rendered to is undefined. Therefore, you should set it for each vertex emitted, and the value for each vertex of the same primitive should be the same.
  
Note that all of the output variables are cleared when EmitVertex() is called from the geometry shader.
+
Note that the value of all output variables are undefined when {{code|EmitVertex()}} is called from the geometry shader.
  
 
GLSL 4.10 defines the following extra outputs:
 
GLSL 4.10 defines the following extra outputs:
  
<source lang="cpp">
+
<source lang="glsl">
 
out int gl_ViewportIndex;
 
out int gl_ViewportIndex;
 
</source>
 
</source>
  
The ''gl_ViewportIndex'' represents the viewport transform and scissor tests that this primitive will be used against. You should use this variable similarly to ''gl_Layer'': always write to it and always write the same value to it for each primitive.
+
The ''gl_ViewportIndex'' represents the viewport transform and scissor tests that this primitive will be used against. You should use this variable similarly to ''gl_Layer'': always write to it and always write the same value to it for each vertex of a primitive.
  
 
== Fragment shader inputs ==
 
== Fragment shader inputs ==
  
<source lang="cpp">
+
<source lang="glsl">
in vec4 gl_FragCoord;
+
in vec4 gl_FragCoord;
in bool gl_FrontFacing;
+
in bool gl_FrontFacing;
in float gl_ClipDistance[];
+
in float gl_ClipDistance[];
in vec2 gl_PointCoord;
+
in vec2 gl_PointCoord;
in int   gl_PrimitiveID;
+
in int gl_PrimitiveID;
 
</source>
 
</source>
  
Line 118: Line 188:
 
GLSL 4.00 adds the following inputs:
 
GLSL 4.00 adds the following inputs:
  
<source lang="cpp">
+
<source lang="glsl">
in int   gl_SampleID;
+
in int gl_SampleID;
in vec2 gl_SamplePosition;
+
in vec2 gl_SamplePosition;
 +
in int gl_SampleMaskIn[];
 
</source>
 
</source>
  
Line 128: Line 199:
  
 
{{note|Using the ''gl_SamplePosition'' variable '''in any way''' will cause the fragment shader to be evaluated per-sample. Since the whole point of multisampling is to avoid that, it's probably not a good idea to do so unless you really need it.}}
 
{{note|Using the ''gl_SamplePosition'' variable '''in any way''' will cause the fragment shader to be evaluated per-sample. Since the whole point of multisampling is to avoid that, it's probably not a good idea to do so unless you really need it.}}
 +
 +
''gl_SampleMaskIn'' represents the sample coverage mask for the currently rasterized fragment. The user must redeclare the size of the sample mask to the implementation-dependent maximum number of samples, divided by 32, rounded up (to get the number of 32-bit integers).
 +
 +
GLSL 4.30 adds the following inputs:
 +
 +
<source lang="glsl">
 +
in int gl_Layer;
 +
in int gl_ViewportIndex;
 +
</source>
 +
 +
''gl_Layer'' and ''gl_ViewportIndex'' both have the values passed from the geometry shader. If no geometry shader is used, they both have the value 0.
  
 
== Fragment shader uniforms ==
 
== Fragment shader uniforms ==
Line 133: Line 215:
 
The fragment shader defines some uniform built-in values for the sake of convenience:
 
The fragment shader defines some uniform built-in values for the sake of convenience:
  
<source lang="cpp">
+
<source lang="glsl">
 
struct gl_DepthRangeParameters
 
struct gl_DepthRangeParameters
 
{
 
{
Line 143: Line 225:
 
</source>
 
</source>
  
This struct provides access to the glDepthRange near and far values. The ''diff'' value is the far value minus the near value.
+
This struct provides access to the {{apifunc|glDepthRange}} near and far values. The ''diff'' value is the far value minus the near value.
  
 
== Fragment shader outputs ==
 
== Fragment shader outputs ==
 
+
<source lang="glsl">
<source lang="cpp">
+
 
out float gl_FragDepth;
 
out float gl_FragDepth;
 
</source>
 
</source>
Line 153: Line 234:
 
The ''gl_FragDepth'' value is the value that will be written to the depth buffer. It will also be used for the depth test. The fragment shader does not have to write to this variable; it will automatically be filled with with ''gl_FragCoord.z''. However, if the fragment shader writes to this variable anywhere, then it must ensure that the value is ''always'' written to, no matter what path is taken through the shader (unless discard is used in the other paths).
 
The ''gl_FragDepth'' value is the value that will be written to the depth buffer. It will also be used for the depth test. The fragment shader does not have to write to this variable; it will automatically be filled with with ''gl_FragCoord.z''. However, if the fragment shader writes to this variable anywhere, then it must ensure that the value is ''always'' written to, no matter what path is taken through the shader (unless discard is used in the other paths).
  
GLSL 4.00 adds the following outputs:
+
GLSL 4.00 adds the following output:
  
<source lang="cpp">
+
<source lang="glsl">
 
out int gl_SampleMask[];
 
out int gl_SampleMask[];
 
</source>
 
</source>
Line 162: Line 243:
  
 
The mask bits will be logically AND'd with the coverage mask computed normally.
 
The mask bits will be logically AND'd with the coverage mask computed normally.
 +
 +
== Compute shader inputs ==
 +
<source lang="glsl">
 +
// Compute shaders require GL 4.3 or ARB_compute_shader
 +
in uvec3 gl_NumWorkGroups;
 +
in uvec3 gl_WorkGroupID;
 +
in uvec3 gl_LocalInvocationID;
 +
in uvec3 gl_GlobalInvocationID;
 +
in uint  gl_LocalInvocationIndex;
 +
</source>
 +
 +
The ''gl_NumWorkGroups'' variable contains the number of workgroups in each dimension passed to {{apifunc|glDispatchCompute}} or {{apifunc|glDispatchComputeIndirect}}.
 +
 +
The ''gl_WorkGroupID'' is the work group that the current invocation is executing in. The values are between 0 and ''gl_NumWorkGroups'' - 1, for each of the three axes.
 +
 +
The ''gl_LocalInvocationID'' contains the invocation within a work group that is being executed. It is between 0 and ''gl_WorkGroupSize'' - 1 (see below), for each of the three axes.
 +
 +
The ''gl_GlobalInvocationID'' variable uniquely identifies this invocation across all other local and global work groups dispatched by the compute dispatch call. It is defined as:
 +
 +
<source lang="glsl">
 +
  gl_GlobalInvocationID = gl_WorkGroupID * gl_WorkGroupSize + gl_LocalInvocationID;
 +
</source>
 +
 +
The ''gl_LocalInvocationIndex'' contains a 1-dimensional representation of ''gl_LocalInvocationID''. It is defined as:
 +
 +
<source lang="glsl">
 +
  gl_LocalInvocationIndex =
 +
          gl_LocalInvocationID.z * gl_WorkGroupSize.x * gl_WorkGroupSize.y +
 +
          gl_LocalInvocationID.y * gl_WorkGroupSize.x +
 +
          gl_LocalInvocationID.x;
 +
</source>
 +
 +
== Compute shader other variables ==
 +
<source lang="glsl">
 +
const uvec3 gl_WorkGroupSize;  // GLSL ≥ 4.30
 +
</source>
 +
 +
The ''gl_WorkGroupSize'' variable is a constant that contains the local work-group size of the shader, in 3 dimensions. It is defined by the [[GLSL_Type_Qualifiers#Layout_qualifiers|layout qualifiers]] ''local_size_x/y/z''. This is a compile-time constant.
 +
 +
  
 
[[Category:OpenGL Shading Language]]
 
[[Category:OpenGL Shading Language]]

Revision as of 15:43, 22 October 2012

The OpenGL Shading Language defines a number of special variables for the various shader stages. These predefined variables (or built-in variables) have special properties. They are usually for communicating with certain fixed-functionality. By convention, all predefined variables start with "gl_"; no user-defined variables may start with this.

Note: This page only describes the core OpenGL shading language pre-defined variables. Any variables that are from the compatibility profiles are not listed here.

Vertex shader inputs

Vertex shaders have the following predefined inputs.

/* no inputs prior to GLSL 1.30 */
 
in int gl_VertexID; /* GLSL ≥ 1.30 */
in int gl_InstanceID; /* GLSL ≥ 1.40 */

The gl_VertexID is the index of the current vertex being processed. For array rendering, this value is the index of the current vertex. For indexed rendering, this is the index fetched from the element buffer for this vertex.

The gl_InstanceID specifies which instance is being rendered, when using instanced rendering.

Vertex shader outputs

Vertex shaders have the following predefined outputs.

out gl_PerVertex
{
  vec4 gl_Position;
  float gl_PointSize;
  float gl_ClipDistance[];
}

gl_PerVertex defines an interface block for outputs. The block is defined so that prefixing the names is not required.

gl_Position is the output position of the current vertex (in clip-space, if there is no geometry shader). It is not necessary to write to this value in a vertex shader, though if you do not, don't be surprised if the primitives you get are not reasonable. You can reasonably omit writing to this variable if you are using transform feedback and shutting off rasterization, or if you are using a geometry shader that will use user-defined outputs to generate positions.

gl_PointSize is the pixel width/height of the point being rasterized. It is only necessary to write to this when rendering points.

gl_ClipDistance allows the shader to set the distance from a vertex to each clip plane. A positive distance means that the vertex is inside/behind the clip plane, and a negative distance means it is outside/in front of the clip plane.

In order to use this variable, the user must manually redeclare it with a size.

Tessellation control shader inputs

/* no tessellation control shaders prior to GLSL 4.00 */
 
in gl_PerVertex
{
    vec4 gl_Position;
    float gl_PointSize;
    float gl_ClipDistance[];
} gl_in[gl_MaxPatchVertices];
 
in int gl_PatchVerticesIn;
in int gl_PrimitiveID;
in int gl_InvocationID;

Tessellation control shader outputs

/* no tessellation control shaders prior to GLSL 4.00 */
 
out gl_PerVertex
{
    vec4 gl_Position;
    float gl_PointSize;
    float gl_ClipDistance[];
} gl_out[];
 
patch out float gl_TessLevelOuter[4];
patch out float gl_TessLevelInner[2];

Tessellation evaluation shader inputs

/* no tessellation evaluation shaders prior to GLSL 4.00 */
 
in gl_PerVertex
{
    vec4 gl_Position;
    float gl_PointSize;
    float gl_ClipDistance[];
} gl_in[gl_MaxPatchVertices];
 
in int gl_PatchVerticesIn;
in int gl_PrimitiveID;
in vec3 gl_TessCoord;
 
patch in float gl_TessLevelOuter[4];
patch in float gl_TessLevelInner[2];

Tessellation evaluation shader outputs

/* no tessellation evaluation shaders prior to GLSL 4.00 */
 
out gl_PerVertex
{
    vec4 gl_Position;
    float gl_PointSize;
    float gl_ClipDistance[];
};

Geometry shader inputs

/* no geometry shaders prior to GLSL 1.50 */
 
in gl_PerVertex
{
  vec4 gl_Position;
  float gl_PointSize;
  float gl_ClipDistance[];
} gl_in[];
 
in int gl_PrimitiveIDIn;

The gl_PerVertex variables contain the values passed from the previous shader stages. Note that in the geometry shader, they must be prefixed by gl_in, which is an interface block array. The size of this array is based on the layout qualifier used for inputs for this geometry shader. You do not have to redeclare this block with a specific size; the system does this for you. As with any array, you can get its length with the length() function.

gl_PrimitiveIDIn is the number of the current primitive being worked on during this rendering call. It is the number of primitives previously processed by the current glDraw*​ rendering call.

GLSL 4.00 and above also have the following definitions:

in int gl_InvocationID;

Geometry shaders can be invoked multiple times over the same primitive with geometry shader instancing; this value specifies the current invocation instance.

Geometry shader outputs

/* no geometry shaders prior to GLSL 1.50 */
 
out gl_PerVertex
{
  vec4 gl_Position;
  float gl_PointSize;
  float gl_ClipDistance[];
};
 
out int gl_PrimitiveID;
out int gl_Layer;

The gl_PerVertex has the same meaning as from the vertex shader stage.

gl_PrimitiveID is a user-defined identifier for the primitive. It is passed directly to the fragment shader (see below). If the fragment shader uses its corresponding input, the value is undefined if the geometry shader does not write to it (OpenGL will automatically fill it in if there is no geometry shader).

The geometry shader should write to this value for the provoking vertex of the output primitive.

gl_Layer is used for rendering to layered framebuffer objects. It specifies the layer that the particular primitive is rendered to.

The gl_Layer variable is assigned to each vertex. If different vertices of a primitive get a different layer value, then OpenGL states that which layer is rendered to is undefined. Therefore, you should set it for each vertex emitted, and the value for each vertex of the same primitive should be the same.

Note that the value of all output variables are undefined when EmitVertex()​ is called from the geometry shader.

GLSL 4.10 defines the following extra outputs:

out int gl_ViewportIndex;

The gl_ViewportIndex represents the viewport transform and scissor tests that this primitive will be used against. You should use this variable similarly to gl_Layer: always write to it and always write the same value to it for each vertex of a primitive.

Fragment shader inputs

in vec4 gl_FragCoord;
in bool gl_FrontFacing;
in float gl_ClipDistance[];
in vec2 gl_PointCoord;
in int gl_PrimitiveID;

gl_FragCoord contains the window-space position of the current sample that this fragment represents. The Z component is the value that will be written to the depth buffer if the user does not override this (see below). The W component is special; it is 1/Wclip. That is, it is 1 divided by the W component of gl_Position output from the vertex or geometry shader.

gl_FrontFacing is true if the primitive is seen from the front, and false if it is the back.

gl_ClipDistance contains the values output from the vertex shader, linearly interpolated across the primitive. As before, it must be sized explicitly.

gl_PointCoord is the location within the area of a point that specifies this fragment's location. This is a normalized value, on the range [0, 1]. The (0,0) origin depends on the point coordinate origin set by OpenGL; the default is the lower-left corner.

gl_PrimitiveID is the value output by the geometry shader, or by OpenGL if no geometry shader was used. It represents the index of the primitive that is being rasterized.

GLSL 4.00 adds the following inputs:

in int gl_SampleID;
in vec2 gl_SamplePosition;
in int gl_SampleMaskIn[];

gl_SampleID is the ID for the current sample being rasterized within the area of the pixel.

gl_SamplePosition is the location of the current sample within the pixel area being rendered. These values are on the range [0, 1].

Note: Using the gl_SamplePosition variable in any way will cause the fragment shader to be evaluated per-sample. Since the whole point of multisampling is to avoid that, it's probably not a good idea to do so unless you really need it.

gl_SampleMaskIn represents the sample coverage mask for the currently rasterized fragment. The user must redeclare the size of the sample mask to the implementation-dependent maximum number of samples, divided by 32, rounded up (to get the number of 32-bit integers).

GLSL 4.30 adds the following inputs:

in int gl_Layer;
in int gl_ViewportIndex;

gl_Layer and gl_ViewportIndex both have the values passed from the geometry shader. If no geometry shader is used, they both have the value 0.

Fragment shader uniforms

The fragment shader defines some uniform built-in values for the sake of convenience:

struct gl_DepthRangeParameters
{
    float near;
    float far;
    float diff;
};
uniform gl_DepthRangeParameters gl_DepthRange;

This struct provides access to the glDepthRange near and far values. The diff value is the far value minus the near value.

Fragment shader outputs

out float gl_FragDepth;

The gl_FragDepth value is the value that will be written to the depth buffer. It will also be used for the depth test. The fragment shader does not have to write to this variable; it will automatically be filled with with gl_FragCoord.z. However, if the fragment shader writes to this variable anywhere, then it must ensure that the value is always written to, no matter what path is taken through the shader (unless discard is used in the other paths).

GLSL 4.00 adds the following output:

out int gl_SampleMask[];

gl_SampleMask is a bitmask that represents the samples, when using multisample rendering, that will be written to. The user must redeclare the size of the sample mask to the implementation-dependent maximum number of samples, divided by 32, rounded up (to get the number of 32-bit integers).

The mask bits will be logically AND'd with the coverage mask computed normally.

Compute shader inputs

// Compute shaders require GL 4.3 or ARB_compute_shader
in uvec3 gl_NumWorkGroups;
in uvec3 gl_WorkGroupID;
in uvec3 gl_LocalInvocationID;
in uvec3 gl_GlobalInvocationID;
in uint  gl_LocalInvocationIndex;

The gl_NumWorkGroups variable contains the number of workgroups in each dimension passed to glDispatchCompute or glDispatchComputeIndirect.

The gl_WorkGroupID is the work group that the current invocation is executing in. The values are between 0 and gl_NumWorkGroups - 1, for each of the three axes.

The gl_LocalInvocationID contains the invocation within a work group that is being executed. It is between 0 and gl_WorkGroupSize - 1 (see below), for each of the three axes.

The gl_GlobalInvocationID variable uniquely identifies this invocation across all other local and global work groups dispatched by the compute dispatch call. It is defined as:

  gl_GlobalInvocationID = gl_WorkGroupID * gl_WorkGroupSize + gl_LocalInvocationID;

The gl_LocalInvocationIndex contains a 1-dimensional representation of gl_LocalInvocationID. It is defined as:

  gl_LocalInvocationIndex =
          gl_LocalInvocationID.z * gl_WorkGroupSize.x * gl_WorkGroupSize.y +
          gl_LocalInvocationID.y * gl_WorkGroupSize.x + 
          gl_LocalInvocationID.x;

Compute shader other variables

const uvec3 gl_WorkGroupSize;   // GLSL ≥ 4.30

The gl_WorkGroupSize variable is a constant that contains the local work-group size of the shader, in 3 dimensions. It is defined by the layout qualifiers local_size_x/y/z. This is a compile-time constant.