Shader Storage Buffer Object |
您所在的位置:网站首页 › opengl支持computeshader › Shader Storage Buffer Object |
Shader Storage Buffer Object
Core in version
4.6
Core since version
4.3
Core ARB extension
ARB_shader_storage_buffer_object
OpenGL Objects
OpenGL Object
Buffer Objects
Buffer Object Streaming
Vertex Buffer Objects
Pixel Buffer Objects
Shader Storage Buffer Objects
Uniform Buffer Objects
Atomic Counters
Vertex Array Objects
Textures
Sampler Objects
Image formats
Pixel transfer operations
Cubemap Textures
Array Textures
Multisample Textures
Rectangle Textures
3D Textures
Buffer Textures
Asynchronous query objects
Framebuffer Objects
Default Framebuffer
Renderbuffer Objects
Unconventional objects:
Sync Objects
Shader and program objects
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: SSBOs can be much larger. The OpenGL spec guarantees that UBOs can be up to 16KB in size (implementations can allow them to be bigger). The spec guarantees that SSBOs can be up to 128MB. Most implementations will let you allocate a size up to the limit of GPU memory. SSBOs are writable, even atomically; UBOs are uniforms. SSBOs reads and writes use incoherent memory accesses, so they need the appropriate barriers, just as Image Load Store operations. 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. SSBO access, all things being equal, will likely be slower than UBO access. SSBOs are generally accessed 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. Contents 1 Shader specification 2 Memory qualifiers 3 Atomic operations 4 OpenGL usage Shader specification Main article: Interface Block (GLSL)SSBOs are declared as interface blocks, using the buffer keyword. They have special layout qualifiers for specifying important aspects of them, such a memory layout and binding qualities. Memory qualifiersStorage blocks, and members thereof, may have memory qualifiers applied to them, which affect how memory operations on those variables are performed. Qualifiers associated with the block apply to all members of that block. coherent Normally, the compiler is free to assume that this shader invocation is the only invocation that modifies values read through this variable. It also can freely assume that other shader invocations may not see values written through this variable. Using this qualifier is required to allow dependent shader invocations to communicate with one another, as it enforces the coherency of memory accesses. Using this requires the appropriate memory barriers to be executed, so that visibility can be achieved. When communicating between shader invocations for different rendering commands, glMemoryBarrier should be used instead of this qualifier. volatile The compiler normally is free to assume that values accessed through variables will only change after memory barriers or other synchronization. With this qualifier, the compiler assumes that the contents of the storage represented by the variable could be changed at any time. restrict Normally, the compiler must assume that you could access the same image/buffer object through separate variables in the same shader. Therefore, if you write to one variable, and read from a second, the compiler assumes that it is possible that you could be reading the value you just wrote. With this qualifier, you are telling the compiler that this particular variable is the only variable that can modify the memory visible through that variable within this shader invocation (other shader stages don't count here). This allows the compiler to optimize reads/writes better. You should use this wherever possible. readonly Normally, the compiler allows you to read and write from variables as you wish. If you use this, the variable can only be used for reading operations (atomic operations are forbidden as they also count as writes). writeonly Normally, the compiler allows you to read and write from variables as you wish. If you use this, the variable can only be used for writing operations (atomic operations are forbidden as they also count as reads). Note: writeonly and readonly are not mutually exclusive. For variables tagged with both qualifiers, it is still possible to query information about the resource. For example, image variables so qualified can still have the image's size looked up. Atomic operationsThere are special atomic functions that can be applied to variables in storage blocks (these can also be applied to Compute Shader shared variables). These only operate on uint or int types, but these can be members of aggregates (structs/arrays) or vector elements (ie: you can atomically access uvec3.x). V · EAll 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 usageTo copy an array of variable size to the SSBO int data[SOME_SIZE]; ... GLuint ssbo; glGenBuffers(1, &ssbo); glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo); glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GLenum usage); //sizeof(data) only works for statically sized C/C++ arrays. glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, ssbo); glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); // unbindOr if you just want to update a part of the already created SSBO glBufferSubData(GL_SHADER_STORAGE_BUFFER, offset, size, data); //to update partiallyNote that the buffer is bound to the binding index 3. It can be assigned to an array in the shader like this: layout(std430, binding = 3) buffer layoutName { int data_SSBO[]; };There can only be one array of variable size per SSBO and it has to be the bottommost variable in the block definition. So this is possible too: layout(std430, binding = 2) buffer anotherLayoutName { int some_int; float fixed_array[42]; float variable_array[]; };The data can be assigned via a struct like this: struct ssbo_data { int foo; float bar[42]; float baz[MY_SIZE]; }; TODO: This section needs to be filled in. |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |