HexoShader Storage Blocks 2014-12-29
In addition ot the read-only access to buffer object that is provided by uniform blocks, buffer objects can also be used for general storage from shaders using shader storage blocks.
difference tetween a uniform block
your shader can write into the shader storage block
and can even perform atomic operations on members of a shader storage block.
1 | #version 430 core |
The members of a shader storage block can be referred to just as any other variable.
Atomic Memory Operations
An atomic operation is a sequence of a read from memory potentially followed by a write to memory that must be uninterrupted for the result to be correct.
Atomic Operations on Shader Storage Blocks:
- atomicAdd(mem, data)
- atomicAnd(mem, data)
- atomicOr(mem, data)
- atomicXor(mem, data)
- atomicMin(mem, data)
- atomicMax(mem, data)
- atomicExchange(mem, data)
- atomicCompSwap(mem, comp, data)
Synchronizing Access to Memory
Memory hazards fall roughly into three categories:
A Read-After-Write(RAW)
the read ends up being executed before the write is complete
A Write-After-Write(WAW)
write to the same memory location twice in a row
you might expect that whatever data was written last would overwrite the data written first and be the values that end up staying in memory.A Write-After-Read(WAR)
only occurs in parallel processing systems
performs a write to memory after another thread believes that it has written to memory
Using Barriers in Your Application
1 | void glMemoryBarrier(GLbitfield barriers); |
- barriers which allows you to specify which of OpenGL’s memory subsystems shoudl obey the barrier and which ones are free to ignore it and continue as they would have.
Value | Mean |
---|---|
GL_ALL_BARRIER_BITS | synchronize everything |
GL_SHADER_STORAGE_BARRIER_BIT | |
GL_UNIFORM_BARRIER_BIT | |
GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT |
The key to remember about glMemoryBarrier() is that the items included in barriers are the destination subsystems and that the mechanism by which you update the data isn’t relevat
Using Barriers in Your Shaders
Just as you can insert memory barriers in your application’s code to control the ordering of memory accesses performed by your shaders relative to your application, you can also insert barriers into your shaders to stop OpenGL from reading or writing memory in some order other thatn what your shader cdoe says.
The basic memory barrier function in GLSL :
1 | void memoryBarrier(); |
If you call memoryBarrier() from your shader code, any memory reads or wirtes that you might ahve performed will complete before the function returns.
Atomic Counters
Atomic counters atre a special type of variable that represents storage that is shared across multiple shader invocations. This storage is backed by a buffer object, and functions are provided in GLSL to increment and decrement the values stored in the buffer. What is special about these operations is that they a atomic
If two shader invocations increment the same counter at the same time, OpenGL will make them take turns.
1 | layout (binding = 0) uniform atomic_uint my_variable; |
1 | GLuint buf; |
1 | glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, buf); |
- to increment an atomic counter
1 | uint atomicCounterIncrement(atomic_uint c); |
- read the current value of the atomic counter
- adds one to it, write the new value back
- return the origin value it read
- to decrement an atomic counter
1 | uint atomicCounterDecrement(atomic_uint c); |
- reads the current value of the atomic counter
- subtracts one from it, writes the value back
- return the new value
notice that this is the opposite of atomicCounterIncrement
- simply get the value of an atomic counter
1 | uint atomicCounter(atomic_uint c); |
- return the value
Turn off writing to the framebuffer:
1 | glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); |
Trun on framebuffer writes:
1 | glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); |
Synchronizing Access to Atomic Counters
glMemoryBarrier() function supports a bit specifically for synchronizing access to atomic counters:
1 | glMemoryBarrier(GL_ATOMIC_COUNTER_BARRIER_BIT) |