Difference between revisions of "Interface Block (GLSL)"

From OpenGL.org
Jump to: navigation, search
m (Alfonse moved page GLSL Interface Blocks to GLSL Interface Block over redirect: Make everything singular, per Wikipedia standard)
(Lots of unstubifying.)
Line 1: Line 1:
'''Interface Blocks''' are ways to group uniforms, inputs, and outputs within [[GLSL]] shaders.
+
{{ infobox feature
 +
| core = 3.1
 +
| core_extension = [http://www.opengl.org/registry/specs/ARB/uniform_buffer_object.txt ARB_uniform_buffer_object], [http://www.opengl.org/registry/specs/ARB/shader_storage_buffer_object.txt ARB_shader_storage_buffer_object]
 +
}}
 +
 
 +
[[GLSL]] shader input, output, uniform, and storage buffer variables can be grouped into '''Interface Blocks'''. These blocks have special syntax and semantics that can be applied to them.
 +
 
 +
== Syntax ==
 +
 
 +
Interface blocks have different semantics in different contexts, but they have the same ''syntax'' regardless of how they are used. Uniform blocks are defined as follows:
 +
 
 +
<source lang=glsl>
 +
interface_qualifier block_name
 +
{
 +
  <define members here>
 +
} instance_name;
 +
</source>
 +
 
 +
This looks like a struct definition, but it is ''not''.
 +
 
 +
{{param|interface_qualifier}} can be one of {{code|in}}, {{code|out}}, {{code|uniform}}, or {{code|buffer}} (the latter requires GL 4.3). This defines what kind of interface block is being created.
 +
 
 +
{{param|block_name}} is the true name for the interface block. When the block is referenced in OpenGL code or otherwise talked about in most contexts, this is the name that is used.
 +
 
 +
{{param|instance_name}} is a GLSL name for one or more instances of the block named {{param|block_name}}. It is optional; if it is present, then all GLSL variables defined within the block must be scoped with the instance name. For example, this defines a uniform block:
 +
 
 +
<source lang=glsl>
 +
uniform MatrixBlock
 +
{
 +
  mat4 projection;
 +
  mat4 modelview;
 +
} matrices;
 +
</source>
 +
 
 +
To access the {{code|projection}} member of this block, you must use {{code|matrices.projection}}.
 +
 
 +
If it were defined as follows:
 +
 
 +
<source lang=glsl>
 +
uniform MatrixBlock
 +
{
 +
  mat4 projection;
 +
  mat4 modelview;
 +
};
 +
</source>
 +
 
 +
You could simply use {{code|projection}} to refer to it. So the interface name acts as a namespace qualifier.
 +
 
 +
The instance name can also define an array of blocks:
 +
 
 +
<source lang=glsl>
 +
uniform MatrixBlock
 +
{
 +
  mat4 projection;
 +
  mat4 modelview;
 +
} matrices[3];
 +
</source>
 +
 
 +
This creates 3 separate interface blocks: {{code|matrices[0]}}, {{code|matrices[1]}}, and {{code|matrices[2]}}. These can have separate binding locations (see below), so they can come from different buffer objects.
 +
 
 +
{{note|The interface name is only used by GLSL. OpenGL always uses the actual block name. Thus, when querying information about the block, one would use "MatrixBlock.modelview" as the uniform name to query the offset of. The array subscript is only used when identifying a specific block to query parameters about it. So the second block would be "MatrixBlock[1]".}}
 +
 
 +
Linking between shader stages allows multiple shaders to use the same block. Interface blocks match with each other based on the block name and the member field definitions. So the same block in different shader stages can have ''different'' instance names.
 +
 
 +
== Input and output ==
 +
 
 +
Input and output blocks are designed to compliment each other. Their primary utility is with geometry or tessellation shaders, as these shaders often work with arrays of inputs/outputs.
 +
 
 +
Data passed between shader stages can be grouped into blocks. If the input is in a block, then the output must also be within a block that uses the same block name and members (but not necessarily the same instance name). For example, a vertex shader can pass data to a geometry shader using these block definitions:
 +
 
 +
<source lang=glsl>
 +
//Vertex Shader
 +
out VertexData
 +
{
 +
  vec3 color;
 +
  vec2 texCoord;
 +
} outData;
 +
 
 +
//Geometry Shader
 +
in VertexData
 +
{
 +
  vec3 color;
 +
  vec2 texCoord;
 +
} inData[];
 +
</source>
 +
 
 +
Notice that the geometry shader block is defined as an array in the geometry shader. It also uses a different instance name. These work perfectly fine; the GS will receive a number of vertices based on the primitive type it is designed to take.
 +
 
 +
== Buffer backed ==
 +
 
 +
Uniform blocks and shader storage blocks work in very similar ways, so this section will explain the features they have in common. Collectively, these are called "buffer-backed blocks."
 +
 
 +
Note that shader storage blocks are a GL 4.3 feature, and thus are not available unless 4.3 or ARB_shader_storage_buffer_objects is defined.
 +
 
 +
=== Matrix storage order ===
 +
 
 +
Because the storage for these blocks comes from [[Buffer Object]]s, matrix ordering becomes important. Matrices can be stored in column or row-major ordering. Layout qualifiers are used to decide which is used on a per-variable basis.
 +
 
 +
Note that this ''does not'' change how GLSL works with them. GLSL matrices are ''always'' column-major. This specification only changes how GLSL fetches the data from the buffer.
 +
 
 +
Defaults can be set with this syntax:
 +
 
 +
layout(row_major) uniform;
 +
 
 +
From this point on, all matrices in uniform blocks are considered row-major. Shader storage blocks are not affected; they would need their own definition ({{code|layout(row_major) buffer;}}).
 +
 
 +
A particular block can have a default set as well:
 +
 
 +
<source lang=glsl>
 +
layout(row_major) uniform MatrixBlock
 +
{
 +
  mat4 projection;
 +
  mat4 modelview;
 +
} matrices[3];
 +
</source>
 +
 
 +
All of the matrices are stored in row-major ordering.
 +
 
 +
Individual variables can be adjusted as well:
 +
 
 +
<source lang=glsl>
 +
layout(row_major) uniform MatrixBlock
 +
{
 +
  mat4 projection;
 +
  layout(column_major) mat4 modelview;
 +
} matrices[3];
 +
</source>
 +
 
 +
{{code|MatrixBlock.projection}} is row-major, but {{code|MatrixBlock.modelview}} is column-major. The default is column-major.
 +
 
 +
=== Memory layout ===
 +
 
 +
The specific size of basic types used by members of buffer-backed blocks is defined by OpenGL. However, implementations are allowed some latitude when assigning padding ''between'' members, as well as reasonable freedom to optimize away unused members. How much freedom implementations are allowed for specific blocks can be changed.
 +
 
 +
There are four memory layout qualifiers: {{code|shared}}, {{code|packed}}, {{code|std140}}, and {{code|std420}}. Defaults can be set the same as for matrix ordering (eg: {{code|layout(packed) buffer;}} sets all shader storage buffer blocks to use {{code|packed}}).
 +
 
 +
{{code|shared}} is the default. This layout means that individual members cannot be optimized out. The name comes from the fact that if you provide the exact same definition (including array counts and the like) to two different programs, OpenGL guarantees that they will have the exact same member variable layouts. Thus, you can query layout information for one, and use it in another.
 +
 
 +
{{code|packed}} gives the implementation the maximum freedom. It can optimize out definitions, rearrange their orders, etc. The layout for a packed block must be queried regardless of how it is defined.
 +
 
 +
{{code|std140}} and {{code|std430}} are layouts that are explicitly defined by the OpenGL standard. Thus, not only are the layouts guaranteed between programs, they are guaranteed ''across implementations''. This is useful for being able to build C or C++ structs that contain exactly the values in the proper order that GLSL's blocks will take.
 +
 
 +
{{code|std430}} can ''only'' be used on shader storage blocks; it offers greater packing and smaller alignment guarantees than {{code|std140}}.
 +
 
 +
=== Block binding ===
 +
 
 +
Each uniform/shader storage block has a binding index. This index references one of a number of slots in the OpenGL context that say which buffer objects to use. When a buffer object is bound to the index reference by a block, then that block will get its data from that buffer.
 +
 
 +
If GL 4.2 or ARB_shading_language_420pack is defined, then the block binding indices can be set directly from the shader:
 +
 
 +
<source lang=glsl>
 +
layout(binding = 3) uniform MatrixBlock
 +
{
 +
  mat4 projection;
 +
  mat4 modelview;
 +
};
 +
</source>
 +
 
 +
Uniform and shader storage blocks have a different set of indices. Uniform block binding indices refer to blocks bound to indices in the {{enum|GL_UNIFORM_BUFFER}} indexed target with {{apifunc|glBindBufferRange}}. Shader storage block binding indices refer to blocks bound to indices in the {{enum|GL_SHADER_STORAGE_BUFFER}} target.
 +
 
 +
For arrays of blocks, the binding syntax sequentially allocates indices. So this definition:
 +
 
 +
<source lang=glsl>
 +
layout(binding = 2) uniform MatrixBlock
 +
{
 +
  mat4 projection;
 +
  mat4 modelview;
 +
} matrices[4];
 +
</source>
 +
 
 +
There will be 4 separate blocks, which use the binding indices 2, 3, 4, and 5.
 +
 
 +
Block bindings can also be set manually from OpenGL. The function to do this depends on whether it is a uniform block or a shader storage block. See their individual sections.
 +
 
 +
Once a binding is assigned, the storage can be bound to the OpenGL context with {{apifunc|glBindBufferRange}} (or {{apifunc|glBindBufferBase}} for the whole buffer). Each type of buffer-backed block has its own target. Uniform blocks use {{enum|GL_UNIFORM_BUFFER}}, and shader storage blocks use {{enum|GL_SHADER_STORAGE_BUFFER}}.
 +
 
 +
=== Uniform blocks ===
 +
 
 +
Uniform blocks cannot use {{code|std140}} layout.
 +
 
 +
To set the block binding from OpenGL, you must first get the index for that uniform block. To do that, you may use one of these two functions:
 +
 
 +
GLuint {{apifunc|glGetProgramResourceIndex}}( GLuint {{param|program​}}, GLenum {{param|programInterface​}}, const char *{{param|name}} );
 +
GLuint {{apifunc|glGetUniformBlockIndex}}( GLuint {{param|program​}}, const char *{{param|name​}} );
 +
 
 +
The first function is only available in GL version 4.3 or if ARB_program_interface_query is available. The latter is always available. If you use {{apifunc|glGetProgramResourceIndex}}, the {{param|programInterface​}} parameter should be {{enum|GL_UNIFORM_BLOCK}}.
 +
 
 +
If {{param|name}} specifies a block that is inactive, or specifies a block that isn't defined in {{param|program}}, then {{enum|GL_INVALID_INDEX}} is returned.
 +
 
 +
Once the index is retrieved, it can be used to set the buffer binding with this function:
 +
 
 +
void {{apifunc|glUniformBlockBinding}}( GLuint {{param|program​}}, GLuint {{param|uniformBlockIndex​}}, GLuint {{param|uniformBlockBinding​}} );
 +
 
 +
This causes the uniform block specified by {{param|uniformBlockIndex​}} in {{param|program​}} to use the uniform buffer binding location {{param|uniformBlockBinding​}}.
 +
 
 +
There are only {{enum|GL_MAX_UNIFORM_BUFFER_BINDINGS}} binding locations available. So {{param|uniformBlockBinding​}} must be less than this value.
 +
 
 +
=== Shader storage blocks ===
 +
 
 +
As with uniform blocks, you must get the index to the shader storage block in order to manually bind it. There is only one function to do this:
 +
 
 +
GLuint {{apifunc|glGetProgramResourceIndex}}( GLuint {{param|program​}}, GLenum {{param|programInterface​}}, const char *{{param|name}} );
 +
 
 +
In this case, {{param|programInterface}} should be {{enum|GL_SHADER_STORAGE_BLOCK​}}.
 +
 
 +
If {{param|name}} specifies a block that is inactive, or specifies a block that isn't defined in {{param|program}}, then {{enum|GL_INVALID_INDEX}} is returned.
 +
 
 +
Once the index is retrieved, it can be used to set the buffer binding with this function:
 +
 
 +
void {{apifunc|glShaderStorageBlockBinding}}( GLuint {{param|program​}}, GLuint {{param|storageBlockIndex​}}, GLuint {{param|storageBlockBinding​}} )
 +
 
 +
This causes the shader storage block specified by {{param|storageBlockIndex​}} in {{param|program​}} to use the shader storage buffer binding location {{param|storageBlockBinding​}}.
 +
 
 +
There are only {{enum|GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS}} binding locations available. So {{param|storageBlockBinding​}} must be less than this value.
  
{{stub}}
 
  
 
[[Category:OpenGL Shading Language]]
 
[[Category:OpenGL Shading Language]]

Revision as of 14:55, 15 August 2012

Interface Block (GLSL)
Core in version 4.5
Core since version 3.1
Core ARB extension ARB_uniform_buffer_object, ARB_shader_storage_buffer_object

GLSL shader input, output, uniform, and storage buffer variables can be grouped into Interface Blocks. These blocks have special syntax and semantics that can be applied to them.

Syntax

Interface blocks have different semantics in different contexts, but they have the same syntax regardless of how they are used. Uniform blocks are defined as follows:

interface_qualifier block_name
{
  <define members here>
} instance_name;

This looks like a struct definition, but it is not.

interface_qualifier​ can be one of in​, out​, uniform​, or buffer​ (the latter requires GL 4.3). This defines what kind of interface block is being created.

block_name​ is the true name for the interface block. When the block is referenced in OpenGL code or otherwise talked about in most contexts, this is the name that is used.

instance_name​ is a GLSL name for one or more instances of the block named block_name​. It is optional; if it is present, then all GLSL variables defined within the block must be scoped with the instance name. For example, this defines a uniform block:

uniform MatrixBlock
{
  mat4 projection;
  mat4 modelview;
} matrices;

To access the projection​ member of this block, you must use matrices.projection​.

If it were defined as follows:

uniform MatrixBlock
{
  mat4 projection;
  mat4 modelview;
};

You could simply use projection​ to refer to it. So the interface name acts as a namespace qualifier.

The instance name can also define an array of blocks:

uniform MatrixBlock
{
  mat4 projection;
  mat4 modelview;
} matrices[3];

This creates 3 separate interface blocks: matrices[0]​, matrices[1]​, and matrices[2]​. These can have separate binding locations (see below), so they can come from different buffer objects.

Note: The interface name is only used by GLSL. OpenGL always uses the actual block name. Thus, when querying information about the block, one would use "MatrixBlock.modelview" as the uniform name to query the offset of. The array subscript is only used when identifying a specific block to query parameters about it. So the second block would be "MatrixBlock[1]".

Linking between shader stages allows multiple shaders to use the same block. Interface blocks match with each other based on the block name and the member field definitions. So the same block in different shader stages can have different instance names.

Input and output

Input and output blocks are designed to compliment each other. Their primary utility is with geometry or tessellation shaders, as these shaders often work with arrays of inputs/outputs.

Data passed between shader stages can be grouped into blocks. If the input is in a block, then the output must also be within a block that uses the same block name and members (but not necessarily the same instance name). For example, a vertex shader can pass data to a geometry shader using these block definitions:

//Vertex Shader
out VertexData
{
  vec3 color;
  vec2 texCoord;
} outData;
 
//Geometry Shader
in VertexData
{
  vec3 color;
  vec2 texCoord;
} inData[];

Notice that the geometry shader block is defined as an array in the geometry shader. It also uses a different instance name. These work perfectly fine; the GS will receive a number of vertices based on the primitive type it is designed to take.

Buffer backed

Uniform blocks and shader storage blocks work in very similar ways, so this section will explain the features they have in common. Collectively, these are called "buffer-backed blocks."

Note that shader storage blocks are a GL 4.3 feature, and thus are not available unless 4.3 or ARB_shader_storage_buffer_objects is defined.

Matrix storage order

Because the storage for these blocks comes from Buffer Objects, matrix ordering becomes important. Matrices can be stored in column or row-major ordering. Layout qualifiers are used to decide which is used on a per-variable basis.

Note that this does not change how GLSL works with them. GLSL matrices are always column-major. This specification only changes how GLSL fetches the data from the buffer.

Defaults can be set with this syntax:

layout(row_major) uniform;

From this point on, all matrices in uniform blocks are considered row-major. Shader storage blocks are not affected; they would need their own definition (layout(row_major) buffer;​).

A particular block can have a default set as well:

layout(row_major) uniform MatrixBlock
{
  mat4 projection;
  mat4 modelview;
} matrices[3];

All of the matrices are stored in row-major ordering.

Individual variables can be adjusted as well:

layout(row_major) uniform MatrixBlock
{
  mat4 projection;
  layout(column_major) mat4 modelview;
} matrices[3];

MatrixBlock.projection​ is row-major, but MatrixBlock.modelview​ is column-major. The default is column-major.

Memory layout

The specific size of basic types used by members of buffer-backed blocks is defined by OpenGL. However, implementations are allowed some latitude when assigning padding between members, as well as reasonable freedom to optimize away unused members. How much freedom implementations are allowed for specific blocks can be changed.

There are four memory layout qualifiers: shared​, packed​, std140​, and std420​. Defaults can be set the same as for matrix ordering (eg: layout(packed) buffer;​ sets all shader storage buffer blocks to use packed​).

shared​ is the default. This layout means that individual members cannot be optimized out. The name comes from the fact that if you provide the exact same definition (including array counts and the like) to two different programs, OpenGL guarantees that they will have the exact same member variable layouts. Thus, you can query layout information for one, and use it in another.

packed​ gives the implementation the maximum freedom. It can optimize out definitions, rearrange their orders, etc. The layout for a packed block must be queried regardless of how it is defined.

std140​ and std430​ are layouts that are explicitly defined by the OpenGL standard. Thus, not only are the layouts guaranteed between programs, they are guaranteed across implementations. This is useful for being able to build C or C++ structs that contain exactly the values in the proper order that GLSL's blocks will take.

std430​ can only be used on shader storage blocks; it offers greater packing and smaller alignment guarantees than std140​.

Block binding

Each uniform/shader storage block has a binding index. This index references one of a number of slots in the OpenGL context that say which buffer objects to use. When a buffer object is bound to the index reference by a block, then that block will get its data from that buffer.

If GL 4.2 or ARB_shading_language_420pack is defined, then the block binding indices can be set directly from the shader:

layout(binding = 3) uniform MatrixBlock
{
  mat4 projection;
  mat4 modelview;
};

Uniform and shader storage blocks have a different set of indices. Uniform block binding indices refer to blocks bound to indices in the GL_UNIFORM_BUFFER indexed target with glBindBufferRange. Shader storage block binding indices refer to blocks bound to indices in the GL_SHADER_STORAGE_BUFFER target.

For arrays of blocks, the binding syntax sequentially allocates indices. So this definition:

layout(binding = 2) uniform MatrixBlock
{
  mat4 projection;
  mat4 modelview;
} matrices[4];

There will be 4 separate blocks, which use the binding indices 2, 3, 4, and 5.

Block bindings can also be set manually from OpenGL. The function to do this depends on whether it is a uniform block or a shader storage block. See their individual sections.

Once a binding is assigned, the storage can be bound to the OpenGL context with glBindBufferRange (or glBindBufferBase for the whole buffer). Each type of buffer-backed block has its own target. Uniform blocks use GL_UNIFORM_BUFFER, and shader storage blocks use GL_SHADER_STORAGE_BUFFER.

Uniform blocks

Uniform blocks cannot use std140​ layout.

To set the block binding from OpenGL, you must first get the index for that uniform block. To do that, you may use one of these two functions:

GLuint glGetProgramResourceIndex( GLuint program​​, GLenum programInterface​​, const char *name​ );
GLuint glGetUniformBlockIndex( GLuint program​​, const char *name​​ );

The first function is only available in GL version 4.3 or if ARB_program_interface_query is available. The latter is always available. If you use glGetProgramResourceIndex, the programInterface​​ parameter should be GL_UNIFORM_BLOCK.

If name​ specifies a block that is inactive, or specifies a block that isn't defined in program​, then GL_INVALID_INDEX is returned.

Once the index is retrieved, it can be used to set the buffer binding with this function:

void glUniformBlockBinding( GLuint program​​, GLuint uniformBlockIndex​​, GLuint uniformBlockBinding​​ );

This causes the uniform block specified by uniformBlockIndex​​ in program​​ to use the uniform buffer binding location uniformBlockBinding​​.

There are only GL_MAX_UNIFORM_BUFFER_BINDINGS binding locations available. So uniformBlockBinding​​ must be less than this value.

Shader storage blocks

As with uniform blocks, you must get the index to the shader storage block in order to manually bind it. There is only one function to do this:

GLuint glGetProgramResourceIndex( GLuint program​​, GLenum programInterface​​, const char *name​ );

In this case, programInterface​ should be GL_SHADER_STORAGE_BLOCK​.

If name​ specifies a block that is inactive, or specifies a block that isn't defined in program​, then GL_INVALID_INDEX is returned.

Once the index is retrieved, it can be used to set the buffer binding with this function:

void glShaderStorageBlockBinding( GLuint program​​, GLuint storageBlockIndex​​, GLuint storageBlockBinding​​ )

This causes the shader storage block specified by storageBlockIndex​​ in program​​ to use the shader storage buffer binding location storageBlockBinding​​.

There are only GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS binding locations available. So storageBlockBinding​​ must be less than this value.