Riyyi
3 months ago
4 changed files with 344 additions and 0 deletions
@ -0,0 +1,9 @@
|
||||
#+TITLE: Documentation |
||||
#+AUTHOR: Riyyi |
||||
#+LANGUAGE: en |
||||
#+OPTIONS: toc:nil |
||||
|
||||
Topics: |
||||
|
||||
- [[./shaders.org][Shaders]] |
||||
- [[./references.org][References]] |
@ -0,0 +1,326 @@
|
||||
#+TITLE: Memory Layout |
||||
#+AUTHOR: Riyyi |
||||
#+LANGUAGE: en |
||||
#+OPTIONS: toc:nil |
||||
|
||||
This chapter is about the memory layout of interface blocks in GLSL. |
||||
An interface block is a group of variables, a struct if you will. |
||||
|
||||
There are 4 types of memory layouts that can be used, where the first two aren't |
||||
widely used as those are implementation dependent and require querying the |
||||
OpenGL API for memory offsets. |
||||
|
||||
- packed |
||||
- shared |
||||
- std140 |
||||
- std430 |
||||
|
||||
** std140 |
||||
|
||||
This type is usable in Uniform Buffer Objects (=UBO=) and Shader Storage Buffer |
||||
Objects (=SSBO=). |
||||
|
||||
** std430 |
||||
|
||||
This type is only usable in Shader Storage Buffer Objects (=SSBO=). |
||||
|
||||
Main points: |
||||
- Memory is organized into chunks. |
||||
- One chunk has 4 slots, 4 bytes per slot. |
||||
- Can't fit? Move to next chunk. |
||||
- An interface block is at least the size of 1 chunk. |
||||
|
||||
The rules: |
||||
|
||||
- Scalar =bool=, =int=, =uint=, =float=, and =double= |
||||
|
||||
#+BEGIN_SRC |
||||
Both the size and alignment are the size of the scalar in basic machine types |
||||
(e.g., sizeof(GLfloat)) |
||||
#+END_SRC |
||||
|
||||
- Two-componment Vectors (e.g., =ivec2=) |
||||
|
||||
#+BEGIN_SRC |
||||
Both the size and alignment are twice the size of the underlying scalar type. |
||||
#+END_SRC |
||||
|
||||
- Three-component Vectors (e.g., =vec3=) and Four-component Vectors (e.g., =vec4=) |
||||
|
||||
#+BEGIN_SRC |
||||
Both the size and alignment are four times the size of the scalar type. However, |
||||
this is only true when the member is part of an array or nested structure |
||||
#+END_SRC |
||||
|
||||
- Array of Scalars and Vectors |
||||
|
||||
#+BEGIN_SRC |
||||
The size of each element in the array will be the same size of the element type, |
||||
where three-component vectors are rounded up to the size four-component |
||||
vectors. This is also the array's alignment. The array's size will be the |
||||
element size times the number of elements. |
||||
#+END_SRC |
||||
|
||||
- Column-major matrix or an array of column-major matrices of size C columns and R rows |
||||
|
||||
#+BEGIN_SRC |
||||
Same layout as an array of N vectors each with R components, where N is the |
||||
total number of columns present. |
||||
#+END_SRC |
||||
|
||||
- Row-major matrix or an array of row-major matrices of size R rows and C columns |
||||
|
||||
#+BEGIN_SRC |
||||
Same layout as an array of N vectors each with C components, where N is the |
||||
total number of rows present. |
||||
#+END_SRC |
||||
|
||||
Both =GLSL= and the =GLM= math library we're using have column-major matrices! |
||||
|
||||
- Single-structure definition or an array of structures |
||||
|
||||
#+BEGIN_SRC |
||||
Structure alignment is the same as the alignment of the biggest structure |
||||
member, where three-component vectors are rounded up to the size of |
||||
four-component vectors. Each structure will start on this alignment, and its |
||||
size will be the space neeeded by its members, according to the previous rules, |
||||
rounded up to a multiple of the structure alignment. |
||||
#+END_SRC |
||||
|
||||
All of the examples described in the following segments are verified by querying |
||||
the OpenGL API. |
||||
|
||||
*** Scalars |
||||
|
||||
These types take up 1 (or 2 with =double=) slot and can appear after anything. |
||||
In the example below you can see that due to the larger alignment, the ~double~ |
||||
is forced to the next chunk. |
||||
|
||||
#+BEGIN_SRC glsl |
||||
// Var Size Alignment Offset |
||||
bool a; // 4 4 0 |
||||
int b; // 4 4 4 |
||||
uint c; // 4 4 8 |
||||
double d; // 8 8 16 |
||||
float e; // 4 4 24 |
||||
#+END_SRC |
||||
|
||||
#+BEGIN_SRC |
||||
Chunks: |
||||
[a][b][c][ ] #1 |
||||
[d][d][e][ ] #2 |
||||
#+END_SRC |
||||
|
||||
*** Two-component Vectors |
||||
|
||||
**** Float |
||||
|
||||
A Vec2 takes up 2 slots, so will be in the first or last half of a chunk. |
||||
|
||||
#+BEGIN_SRC glsl |
||||
// Var Size Alignment Offset |
||||
vec2 a; // 8 8 0 |
||||
float b; // 4 4 8 |
||||
#+END_SRC |
||||
|
||||
#+BEGIN_SRC |
||||
Chunks: |
||||
[a][a][b][ ] #1 |
||||
#+END_SRC |
||||
|
||||
#+BEGIN_SRC glsl |
||||
// Var Size Alignment Offset |
||||
float a; // 4 4 0 |
||||
vec2 b; // 8 8 8 |
||||
#+END_SRC |
||||
|
||||
#+BEGIN_SRC |
||||
Chunks: |
||||
[a][ ][b][b] #1 |
||||
#+END_SRC |
||||
|
||||
**** Double |
||||
|
||||
#+BEGIN_SRC glsl |
||||
// Var Size Alignment Offset |
||||
float a; // 4 4 0 |
||||
dvec2 b; // 16 16 16 |
||||
#+END_SRC |
||||
|
||||
#+BEGIN_SRC |
||||
Chunks: |
||||
[a][ ][ ][ ] #1 |
||||
[b][b][b][b] #2 |
||||
#+END_SRC |
||||
|
||||
*** Three-component and Four-component Vectors |
||||
|
||||
A Vec3 takes up 3 slots, the alignment is 4 slots so only fits at the start of a |
||||
chunk. |
||||
|
||||
#+BEGIN_SRC glsl |
||||
// Var Size Alignment Offset |
||||
vec3 a; // 12 16 0 |
||||
float b; // 4 4 12 |
||||
vec4 c; // 16 16 16 |
||||
#+END_SRC |
||||
|
||||
#+BEGIN_SRC |
||||
Chunks: |
||||
[a][a][a][b] #1 |
||||
[c][c][c][c] #2 |
||||
#+END_SRC |
||||
|
||||
#+BEGIN_SRC glsl |
||||
// Var Size Alignment Offset |
||||
float a; // 4 4 0 |
||||
vec3 b; // 12 16 16 |
||||
vec4 c; // 16 16 32 |
||||
#+END_SRC |
||||
|
||||
#+BEGIN_SRC |
||||
Chunks: |
||||
[a][ ][ ][ ] #1 |
||||
[b][b][b][ ] #2 |
||||
[c][c][c][c] #3 |
||||
#+END_SRC |
||||
|
||||
*** Array of Scalars and Vectors |
||||
|
||||
#+BEGIN_SRC glsl |
||||
// Var Size Alignment Offset |
||||
float[3] a; // 12 4 0 |
||||
float b; // 4 4 12 |
||||
float c; // 4 4 16 |
||||
float[3] d; // 12 4 20 |
||||
#+END_SRC |
||||
|
||||
#+BEGIN_SRC |
||||
Chunks: |
||||
[a][a][a][b] #1 |
||||
[c][d][d][d] #1 |
||||
#+END_SRC |
||||
|
||||
*Note* the optimizations in the alignment and strides are not applicable to |
||||
~vec3~ elements, these remain unchanged from =std140=. |
||||
|
||||
#+BEGIN_SRC glsl |
||||
// Var Size Alignment Offset |
||||
float a; // 4 4 0 |
||||
vec3[3] b; // 48 16 16 |
||||
float c; // 4 4 64 |
||||
float d; // 4 4 68 |
||||
vec2[2] e; // 16 8 72 |
||||
float f; // 4 4 88 |
||||
#+END_SRC |
||||
|
||||
#+BEGIN_SRC |
||||
Chunks: |
||||
[a][ ][ ][ ] #1, offset: 0 |
||||
[b][b][b][ ] #2, offset: 16 |
||||
[b][b][b][ ] #3, offset: 32 |
||||
[b][b][b][ ] #4, offset: 48 |
||||
[c][d][e][e] #5, offset: 64 |
||||
[e][e][f][ ] #6, offset: 80 |
||||
#+END_SRC |
||||
|
||||
*Note* the offset needs to be a multiple of the alignment, forcing an entire |
||||
empty chunk in the example below. |
||||
|
||||
#+BEGIN_SRC glsl |
||||
// Var Size Alignment Offset |
||||
float a; // 4 4 0 |
||||
dvec2[2] b; // 32 16 16 |
||||
dvec3[2] c; // 64 32 64 |
||||
float d; // 4 4 128 |
||||
#+END_SRC |
||||
|
||||
#+BEGIN_SRC |
||||
Chunks: |
||||
[a][ ][ ][ ] #1, offset: 0 |
||||
[d][d][d][d] #2, offset: 16 |
||||
[d][d][d][d] #3, offset: 32 |
||||
[ ][ ][ ][ ] #4, offset: 48 |
||||
[c][c][c][c] #5, offset: 64 |
||||
[c][c][ ][ ] #6, offset: 80 |
||||
[c][c][c][c] #7, offset: 96 |
||||
[c][c][ ][ ] #8, offset: 112 |
||||
[d][ ][ ][ ] #9, offset: 128 |
||||
#+END_SRC |
||||
|
||||
*** Matrices |
||||
|
||||
Alignment is the same as an array of 1 “row” of the matrix. |
||||
No padding between the “rows” of a matrix, but will pad at the end. |
||||
|
||||
#+BEGIN_SRC glsl |
||||
// Var Size Alignment Offset |
||||
float a; // 4 4 0 |
||||
mat2 b; // 16 8 8 |
||||
vec2 c; // 4 4 24 |
||||
float d; // 4 4 32 |
||||
mat2[2] e; // 32 8 40 |
||||
float f; // 4 4 72 |
||||
#+END_SRC |
||||
|
||||
#+BEGIN_SRC |
||||
Chunks: |
||||
[a][ ][b][b] #1, offset: 0 |
||||
[b][b][c][c] #2, offset: 16 |
||||
[d][ ][e][e] #3, offset: 32 |
||||
[e][e][e][e] #4, offset: 48 |
||||
[e][e][f][ ] #5, offset: 64 |
||||
#+END_SRC |
||||
|
||||
TODO: Add more examples |
||||
|
||||
*** Structs |
||||
|
||||
Alignment same as biggest struct member. Size is the size of all members, |
||||
rounded up to a multiple of the alignment. |
||||
|
||||
In the example below you can see that the ~Stuff~ struct, including padding |
||||
between members, is 20 bytes in size. To make that a multiple of the alignment |
||||
additional padding needs to be put at the end, to make the total size 24 bytes. |
||||
|
||||
Each element in the array of structs will apply the alignment again, as seen |
||||
with ~Stuff[1].a~. |
||||
|
||||
#+BEGIN_SRC glsl |
||||
struct Stuff { |
||||
float a; |
||||
vec2 b; |
||||
float c; |
||||
}; |
||||
|
||||
// Var Size Alignment Offset |
||||
Stuff a; // 20 8 |
||||
a.a; // 4 4 0 |
||||
a.b; // 8 8 8 |
||||
a.c; // 4 4 16 |
||||
float b; // 4 4 24 |
||||
Stuff[2] c; // 44 8 |
||||
c.a; // 4 4 32 |
||||
c.b; // 8 8 40 |
||||
c.c; // 4 4 48 |
||||
float d; // 4 4 80 |
||||
#+END_SRC |
||||
|
||||
#+BEGIN_SRC |
||||
Chunks: |
||||
[a][ ][a][a] #1, offset: 0 |
||||
[a][ ][b][ ] #2, offset: 16 |
||||
[c][ ][c][c] #3, offset: 32 |
||||
[c][ ][c][ ] #4, offset: 48 |
||||
[c][c][c][ ] #5, offset: 64 |
||||
[d][ ][ ][ ] #6, offset: 80 |
||||
#+END_SRC |
||||
|
||||
TODO: Add more examples |
||||
|
||||
* References |
||||
|
||||
- https://learnopengl.com/Advanced-OpenGL/Advanced-GLSL |
||||
- https://www.khronos.org/opengl/wiki/Interface_Block_(GLSL)#Memory_layout |
||||
- [[https://www.oreilly.com/library/view/opengl-programming-guide/9780132748445/app09lev1sec2.html][The std140 Layout Rules]] |
||||
- [[https://www.youtube.com/watch?v=JPvbRko9lBg][(YouTube) WebGL 2: Uniform Buffer Objects]] |
Loading…
Reference in new issue