Disclosure: This article was generated with AI for the FrameSprite team, which has a commercial interest in FrameSprite. It received a separate AI editorial review against the cited sources. Executed synthetic fixtures are identified with their runtime and limits; no other editor, engine, production or performance test is implied.
Calculate each BC-compressed DDS mip level from whole compression blocks. Do not keep dividing byte counts by four after the dimensions become smaller than a block. The smallest mip still occupies a block, even if it contains only a few logical pixels.
Key takeaway: Mip dimensions shrink, but compressed storage has a minimum block size. Validate the emitted mip count rather than assuming every file contains a complete chain.
Start with a non-square texture
The authored example uses a 7 by 3 BC3-style texture with 16-byte blocks and a legacy 128-byte DDS header. Its full dimension chain is 7×3, 3×1 and 1×1. This is a byte-layout exercise, not a claim that every engine accepts those source dimensions.
The Microsoft DDS layout documentation gives block-based level sizing. For this selected format:
blocks_x = max(1, (width + 3) // 4)
blocks_y = max(1, (height + 3) // 4)
level_bytes = blocks_x * blocks_y * 16
| Level dimensions | Payload bytes | Offset in the authored file layout |
|---|---|---|
| 7×3 | 32 | 128 |
| 3×1 | 16 | 160 |
| 1×1 | 16 | 176 |
The payload totals 64 bytes and the authored file layout totals 192. Repeated quartering would incorrectly predict 32, 8 and 2 bytes.
Read the header before choosing the formula
Identify the compression format and its block byte size. An eight-byte BC1 block and a sixteen-byte BC3 block do not have the same payload calculation. Also account for any extended header, array layers, faces or additional surfaces in the actual file.
The DirectXTex DDS I/O notes document compatibility handling for older files and partial blocks. A validator should report its accepted profile instead of silently guessing which historical convention a damaged file intended.
Do not equate a partial chain with corrupted pixels
Some files intentionally contain fewer mip levels than a full chain. Validate the declared count, byte ranges and the target importer's capabilities separately. A Godot DDS import report illustrates a real partial-mip compatibility problem. It concerns the reported versions and files; it does not prove a current engine-wide failure.
When a target rejects a file, preserve the original header and level-size report. Re-export a compatible file from the source rather than adding zero bytes until a size check happens to pass.
Recorded arithmetic and failure control
Python 3.12.10 ran three assertions in the checker. The result records all level offsets, sizes and the 192-byte total. The input fixes the dimensions, block bytes and legacy header assumption. No DDS file was decoded, no BC encoder was run and no GPU texture was created.
Check the rest of the delivery contract
Use the GPU-compression fallback guide for target capability, the texture-memory budget guide for runtime allocation planning, and the asset-version manifest guide to keep the validated file paired with its release metadata.
The final acceptance test is still the target build loading the exact exported file with the intended mip count. Correct byte arithmetic is a useful preflight step, not a substitute for that import test.
Editorial ownership
Prepared by the workflow team, which has a commercial relationship with this site. This guide was drafted with AI assistance; independent editorial review is recorded separately. Report a technical correction with the relevant input, tool version and observed result.
Top comments (0)