Difference between revisions of "Shader Storage Buffer Object"

From OpenGL.org
Jump to: navigation, search
(Atomic operations)
(Shader specification: Describing non-block buffer variables.)
 
(11 intermediate revisions by 2 users not shown)
Line 7: Line 7:
 
}}
 
}}
  
A '''Shader Storage Buffer Object''' is a [[Buffer Object]] that is used to store and retrieve data from [[GLSL]].
+
A '''Shader Storage Buffer Object''' is a [[Buffer Object]] that is used to store and retrieve data from within the [[OpenGL Shading Language]].
  
== Overview ==
+
SSBOs are a lot like [[Uniform Buffer Object]]s. Shader storage blocks are defined by [[Interface Block (GLSL)]]s in almost the same way as uniform blocks. Buffer objects that store SSBOs are bound to SSBO binding points, just as buffer objects for uniforms are bound to UBO binding points. And so forth.
 
+
SSBOs are a lot like [[Uniform Buffer Object]]s. Shader storage blocks are defined almost identically to uniform blocks. SSBOs are bound to SSBO binding points, just as UBOs are bound to UBO binding points. And so forth.
+
  
 
The major differences between them are:
 
The major differences between them are:
  
# SSBOs are typically much larger. The smallest required UBO size is 16KB; the smallest required SSBO size is 16'''MB''', and typical sizes will be on the order of the size of GPU memory.
+
# SSBOs can be much larger. The smallest required UBO size is 16KB; the smallest required SSBO size is 16'''MB''', and typical sizes will be on the order of the size of GPU memory.
# SSBOs are writable, even atomically; UBOs are {{code|uniform}}s. SSBOs have the same memory characteristics as [[Image Load Store]] operations, so they need appropriate memory barriers.
+
# SSBOs are writable, even atomically; UBOs are {{code|uniform}}s. SSBOs reads and writes use [[Incoherent Memory Access|incoherent memory accesses]], so they need the appropriate barriers, just as [[Image Load Store]] operations.
# SSBOs can have unbounded storage, up to the buffer range bound; UBOs must have a specific, fixed storage size. This means that you can have an array of arbitrary length in an SSBO. The actual size of the array, based on the range of the buffer bound, can be queried at runtime in the shader using the {{code|length}} function on the unbounded array variable.
+
# SSBOs can have variable storage, up to whatever buffer range was bound for that particular buffer; UBOs must have a specific, fixed storage size. This means that you can have an array of arbitrary length in an SSBO (at the end, rather). The actual size of the array, based on the range of the buffer bound, can be queried at runtime in the shader using the {{code|length}} function on the unbounded array variable.
 +
# SSBO access, all things being equal, will likely be slower than UBO access. SSBOs generally are accesses like buffer textures, while UBO data is accessed through internal shader-accessible memory reads. At the very least, UBOs will be no slower than SSBOs.
  
 
Functionally speaking, SSBOs can be thought of as a much nicer interface to [[Buffer Texture]]s when accessed via [[Image Load Store]].
 
Functionally speaking, SSBOs can be thought of as a much nicer interface to [[Buffer Texture]]s when accessed via [[Image Load Store]].
  
== Atomic operations ==
+
== Shader specification ==
 +
{{main|Interface Block (GLSL)}}
  
There are special atomic functions that can be applied to buffer variables (and to compute shader {{code|shared}} variables). They only take {{code|uint}} or {{code|int}} types, but these can be members of aggregates (structs/arrays) or vector elements (ie: you can atomically access {{code|uvec3.x}}).
+
There are two ways to declare an SSBO in a shader. The first way is to declare a [[Buffer Backed Interface Block]], using the {{code|buffer}} keyword.
  
All of the atomic functions return the '''''original''''' value.
+
As an alternative, a single global variable can be declared as an SSBO. These are called "buffer variables". Each individual variable declaration is a separate SSBO. They can use any non-[[Opaque Type]]s, including user-defined arrays and structs.
  
The atomic operations are (where "''n''int" can be {{code|int}} or {{code|uint}}):
+
Usually, buffer variables are declared as arrays. As with interface blocks for SSBOs, buffer variable arrays can have the first index declared as just {{code|[]}}. This means that the length of the array will be determined at runtime, based on the amount of storage in the buffer object range bound when rendering.
{{clear float}}
+
 
''n''int atomicAdd(inout ''n''int {{param|mem}}, ''n''int {{param|data}})
+
== Atomic operations ==
''n''int atomicMin(inout ''n''int {{param|mem}}, ''n''int {{param|data}})
+
''n''int atomicMax(inout ''n''int {{param|mem}}, ''n''int {{param|data}})
+
''n''int atomicAnd (inout ''n''int {{param|mem}}, ''n''int {{param|data}})
+
''n''int atomicOr(inout ''n''int {{param|mem}}, ''n''int {{param|data}})
+
''n''int atomicXor(inout ''n''int {{param|mem}}, ''n''int {{param|data}})
+
''n''int atomicExchange(inout ''n''int {{param|mem}}, ''n''int {{param|data}})
+
''n''int atomicCompSwap(inout ''n''int {{param|mem}}, ''n''int {{param|compare}}, ''n''int {{param|data}})
+
  
The last function bears some explanation. It will swap {{param|mem}} with {{param|data}} if {{param|compare}} is equal to the current value of {{param|mem}}.
+
There are special atomic functions that can be applied to buffer variables (and also to compute shader {{code|shared}} variables). They only take {{code|uint}} or {{code|int}} types, but these can be members of aggregates (structs/arrays) or vector elements (ie: you can atomically access {{code|uvec3.x}}).
 +
{{snippet|:Atomic Variable Operations}}
  
 +
== OpenGL usage ==
 +
{{todo}}
  
{{stub}}
 
  
 
[[Category:Objects]]
 
[[Category:Objects]]
 
[[Category:Buffer Objects]]
 
[[Category:Buffer Objects]]
 
[[Category:OpenGL Shading Language]]
 
[[Category:OpenGL Shading Language]]

Latest revision as of 21:56, 4 May 2015

Shader Storage Buffer Object
Core in version 4.5
Core since version 4.3
Core ARB extension ARB_shader_storage_buffer_object

A Shader Storage Buffer Object is a Buffer Object that is used to store and retrieve data from within the OpenGL Shading Language.

SSBOs are a lot like Uniform Buffer Objects. Shader storage blocks are defined by Interface Block (GLSL)s in almost the same way as uniform blocks. Buffer objects that store SSBOs are bound to SSBO binding points, just as buffer objects for uniforms are bound to UBO binding points. And so forth.

The major differences between them are:

  1. SSBOs can be much larger. The smallest required UBO size is 16KB; the smallest required SSBO size is 16MB, and typical sizes will be on the order of the size of GPU memory.
  2. SSBOs are writable, even atomically; UBOs are uniform​s. SSBOs reads and writes use incoherent memory accesses, so they need the appropriate barriers, just as Image Load Store operations.
  3. SSBOs can have variable storage, up to whatever buffer range was bound for that particular buffer; UBOs must have a specific, fixed storage size. This means that you can have an array of arbitrary length in an SSBO (at the end, rather). The actual size of the array, based on the range of the buffer bound, can be queried at runtime in the shader using the length​ function on the unbounded array variable.
  4. SSBO access, all things being equal, will likely be slower than UBO access. SSBOs generally are accesses like buffer textures, while UBO data is accessed through internal shader-accessible memory reads. At the very least, UBOs will be no slower than SSBOs.

Functionally speaking, SSBOs can be thought of as a much nicer interface to Buffer Textures when accessed via Image Load Store.

Shader specification

There are two ways to declare an SSBO in a shader. The first way is to declare a Buffer Backed Interface Block, using the buffer​ keyword.

As an alternative, a single global variable can be declared as an SSBO. These are called "buffer variables". Each individual variable declaration is a separate SSBO. They can use any non-Opaque Types, including user-defined arrays and structs.

Usually, buffer variables are declared as arrays. As with interface blocks for SSBOs, buffer variable arrays can have the first index declared as just []​. This means that the length of the array will be determined at runtime, based on the amount of storage in the buffer object range bound when rendering.

Atomic operations

There are special atomic functions that can be applied to buffer variables (and also to compute shader shared​ variables). They only take uint​ or int​ types, but these can be members of aggregates (structs/arrays) or vector elements (ie: you can atomically access uvec3.x​).

V · E

All of the atomic functions return the original value. The term "nint" can be int​ or uint​.

nint atomicAdd(inout nint mem​, nint data​)

Adds data​ to mem​.

nint atomicMin(inout nint mem​, nint data​)

The mem​'s value is no lower than data​.

nint atomicMax(inout nint mem​, nint data​)

The mem​'s value is no greater than data​.

nint atomicAnd (inout nint mem​, nint data​)

mem​ becomes the bitwise-and between mem​ and data​.

nint atomicOr(inout nint mem​, nint data​)

mem​ becomes the bitwise-or between mem​ and data​.

nint atomicXor(inout nint mem​, nint data​)

mem​ becomes the bitwise-xor between mem​ and data​.

nint atomicExchange(inout nint mem​, nint data​)

Sets mem​'s value to data​.

nint atomicCompSwap(inout nint mem​, nint compare​, nint data​)

If the current value of mem​ is equal to compare​, then mem​ is set to data​. Otherwise it is left unchanged.

OpenGL usage