Skip to content

bgfx::calcTextureSize() is wrong for compressed format mipchain #3434

@hypernewbie

Description

@hypernewbie

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions