Skip to content

Commit 4797695

Browse files
More alignment examples for BDA (#340)
1 parent 4313b18 commit 4797695

File tree

1 file changed

+82
-1
lines changed

1 file changed

+82
-1
lines changed

chapters/buffer_device_address.adoc

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,88 @@ OpStore %ptr %obj Aligned 16
8181

8282
Shading languages will have a default, but can allow you to align it explicitly (ex `buffer_reference_alignment`).
8383

84-
The goal of this alignment is this is a promise for how aligned this specific pointer is. The user is responsible to confirm the address they use is aligned to it.
84+
The goal of this alignment is this is a promise for how aligned this specific pointer is.
85+
The compiler has no idea what the address will be when the shader is compiled.
86+
By providing an alignment it can generate valid code to match the requirement.
87+
The user is responsible to confirm the address they use is aligned to it.
88+
89+
[source,glsl]
90+
----
91+
layout(buffer_reference, buffer_reference_align = 64) buffer MyBDA {
92+
uint data;
93+
};
94+
95+
MyBDA ptr_a; // at 0x1000
96+
MyBDA ptr_b; // at 0x1010
97+
MyBDA ptr_c; // at 0x1040
98+
99+
ptr_a.data = 0; // (Aligned 64) valid!
100+
ptr_b.data = 0; // (Aligned 64) invalid!
101+
ptr_c.data = 0; // (Aligned 64) valid!
102+
----
103+
104+
When deciding on an alignment, the minimum value will always be the size greater than or equal to the largest scalar/component type in the block.
105+
106+
[source,glsl]
107+
----
108+
// alignment must be at least 4
109+
layout(buffer_reference) buffer MyBDA {
110+
vec4 a; // scalar is float
111+
};
112+
113+
// alignment must be at least 1
114+
layout(buffer_reference) buffer MyBDA {
115+
uint8_t a; // scalar is 8-bit int
116+
};
117+
118+
// alignment must be at least 8
119+
layout(buffer_reference) buffer MyBDA {
120+
uint a; // 32-bit
121+
double b; // 64-bit
122+
};
123+
----
124+
125+
=== Alignment Example
126+
127+
To help explain alignment, lets take an example of loading an array of vectors
128+
129+
[source,glsl]
130+
----
131+
layout(buffer_reference, buffer_reference_align = ???) buffer MyBDA {
132+
uvec4 data[];
133+
};
134+
135+
MyBDA ptr; // at 0x1000
136+
ptr.data[i] = uvec4(0);
137+
----
138+
139+
Here we have 2 options, we could set the `Aligned` to be `4` or `16`.
140+
141+
If we set alignment to `16` we are letting the compiler know it can load 16 bytes at a time, so it will hopefully do a vector load/store on the memory.
142+
143+
If we set alignment to `4` the compiler will likely have no way to infer the real alignment and will now do 4 scalar int load/store on the memory.
144+
145+
[NOTE]
146+
====
147+
Some GPUs can do vector load/store even on unaligned addresses.
148+
====
149+
150+
For the next case, if we had `uvec3` instead of `uvec4` such as
151+
152+
[source,glsl]
153+
----
154+
layout(buffer_reference, buffer_reference_align = 4, scalar) buffer MyBDA {
155+
uvec3 data[];
156+
};
157+
158+
data[0]; // 0x1000
159+
data[1]; // 0x100C
160+
data[2]; // 0x1018
161+
data[3]; // 0x1024
162+
----
163+
164+
We know that setting the alignment to `16` would be violated at `data[1]` and therefore we need to use an alignment of `4` in this case.
165+
Luckily shading languages will help do this for you as seen in both link:https://godbolt.org/z/jWGKax1ed[glslang] and link:https://godbolt.org/z/Y7xW3Mfd4[slang] .
85166

86167
=== Nullptr
87168

0 commit comments

Comments
 (0)