diff --git a/doc/README.org b/doc/README.org new file mode 100644 index 0000000..65dbf02 --- /dev/null +++ b/doc/README.org @@ -0,0 +1,9 @@ +#+TITLE: Documentation +#+AUTHOR: Riyyi +#+LANGUAGE: en +#+OPTIONS: toc:nil + +Topics: + +- [[./shaders.org][Shaders]] +- [[./references.org][References]] diff --git a/doc/memory-layout.org b/doc/memory-layout.org new file mode 100644 index 0000000..824606a --- /dev/null +++ b/doc/memory-layout.org @@ -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]] diff --git a/doc/references.org b/doc/references.org new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/doc/references.org @@ -0,0 +1 @@ + diff --git a/doc/shaders.org b/doc/shaders.org new file mode 100644 index 0000000..ac29bb6 --- /dev/null +++ b/doc/shaders.org @@ -0,0 +1,8 @@ +#+TITLE: Shaders +#+AUTHOR: Riyyi +#+LANGUAGE: en +#+OPTIONS: toc:nil + +Topics: + +- [[./memory-layout.org][Memory Layout]]