The idea of this code is to say, "Given a particular (object) instance size, how many bytes of memory are used if the allocator has to round-up object sizes to some power-of-two multiple." Note that if the instance size is already a multiple of the power of two (e.g. 8), then no rounding-up is needed.
It is often the case that memory needs to be allocated in multiples of the hardware's word size in bytes. On a 32-bit platform that would mean a multiple of 4, on 64-bit, a multiple of 8. Note however that the multiple (and thus minOffsetAlignment
) must be a power of 2 (the author of this code, for better or worse, is 100% assuming the person calling this function knows this).
Let's assume for the rest of my answer that we're working with a hardware word size of 64-bit, and that our platform must allocate memory in chunks of 8 bytes (64 bits divided by 8 bits per byte == 8 bytes). So minOffsetAlignment
will be passed as 8.
Consequently, if the instance size is 1-8 bytes, our function must return 8. If it's 9-16 bytes, it must return 16, and so on.
This answer shows how to round up a value to some nearest integer provided the value being rounded isn't already a multiple of that integer.
In the case of rounding up to the nearest multiple of 8, the procedure is to add 7, then do integer division to divide by 8, then multiply by 8.
So:
(0 + 7) / 8 * 8 == 0 // a zero-byte instance requires zero memory bytes
(1 + 7) / 8 * 8 == 8 // a one-byte instance requires eight memory bytes
(2 + 7) / 8 * 8 == 8 // a two-byte instance requires eight memory bytes
...
(8 + 7) / 8 * 8 == 8 // an eight-byte instance requires eight memory bytes
(9 + 7) / 8 * 8 == 16 // a nine-byte instance requires sixteen memory bytes
...
What the code in your question is doing is exactly the above algorithm, but it's using bitwise operations instead of addition, division, and multiplication which on some hardware is faster.
Now, how does it do this?
First we have to get the (instanceSize + 7)
part. That's here:
(instanceSize + minOffsetAlignment - 1)
Then we have to divide it by 8, truncate the remainder, and multiply the result of the division by 8.
The last part does that all in one step, and this explains why minOffsetAlignment
had to be a power of two.
First, we see:
minOffsetAlignment - 1
If minOffsetAlignment
is 8, then its binary value is 0b00001000
.
Subtracting 1 from 8 gives 7, which in binary is 0b00000111
.
Now the complement of 7 is taken:
~(minOffsetAlignment - 1)
This inverts all the bits so we get ...1111000
(for a 64-bit integer such as VkDeviceSize
there are 61 leading 1's and 3 trailing 0's).
Now, putting the whole statement together:
(instanceSize + minOffsetAlignment - 1) & ~(minOffsetAlignment - 1)
We see the &
operator will clear the last three bits of whatever the result of (instanceSize + minOffsetAlignment - 1)
is.
This forces the return value to be a multiple of 8 (since any binary integer with the last three bits 0 is a multiple of 8), but given that we already added 7 it also rounded it up to the nearest multiple of 8 provided instanceSize
wasn't already a multiple of 8.