-
Notifications
You must be signed in to change notification settings - Fork 2k
Description
The correct mipchain size is calculated un-rounded, and then rounded up per mip. Instead, bgfx::calcTextureSize rounds up per-mip, and sizes down the mip from the rounded up value, resulting in a larger value than expected.
GLI library implements this correctly, and was used as the reference here.
BC1 texture example 1920x1080:
BGFX mipchain:
1920 x 1080 = 1036800 (total 1036800)
960 x 540 = 259200 (total 1296000)
480 x 272 = 65280 (total 1361280)
240 x 136 = 16320 (total 1377600)
120 x 69 = 4080 (total 1381680)
60 x 36 = 1080 (total 1382760)
32 x 20 = 320 (total 1383080)
16 x 12 = 96 (total 1383176)
8 x 8 = 32 (total 1383208)
4 x 4 = 8 (total 1383216)
4 x 4 = 8 (total 1383224)
Expected correct mipchain:
1920 x 1080 = 1036800 (total 1036800)
960 x 540 = 259200 (total 1296000)
480 x 270 = 65280 (total 1361280)
240 x 135 = 16320 (total 1377600)
120 x 67 = 4080 (total 1381680)
60 x 33 = 1080 (total 1382760)
30 x 16 = 256 (total 1383016)
15 x 8 = 64 (total 1383080)
7 x 4 = 16 (total 1383096)
3 x 2 = 8 (total 1383104)
1 x 1 = 8 (total 1383112)
From the above you can see even though the 60 x 33 mip matches, the 30x16 mip gets incorrectly sized up to 30x20.
ref:
https://registry.khronos.org/OpenGL/specs/gl/glspec46.core.pdf
section 8.14.3
A texture is mipmap complete if:
...
The dimensions of the images follow the sequence described in sec-
tion 8.14.3.
The storage per-mip is rounded up to 4x4 blocks, but the width + height sequence does not change as a result. This matches GL_TEXTURE_COMPRESSED_IMAGE_SIZE size return and also matches GLI, which implements the spec. Other APIs such as DX, vulkan and proprietary console APIs have the same storage mechanism that GL describes here.