Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

imageSize set incorrectly for unpacked cubemaps #40

Closed
jimblackler opened this issue Jun 19, 2019 · 5 comments
Closed

imageSize set incorrectly for unpacked cubemaps #40

jimblackler opened this issue Jun 19, 2019 · 5 comments

Comments

@jimblackler
Copy link

There's either a problem with my understanding and use of the tools or a problem with the KTX output by basis.

I am trying to use basis to convert six images into KTX files each containing a cubemap.
I have the six images (files from here https://github.com/ARM-software/opengl-es-sdk-for-android/tree/master/samples/advanced_samples/Skybox/assets converted into PNGs with imagemagick).

I run
basisu greenhouse_skybox-*.png -tex_type cubemap -output_file cubemap.basis

The output is:

Basis Universal GPU Texture Compressor Reference Encoder v1.07.00, Copyright (C) 2017-2019 Binomial LLC, All rights reserved
Processing 6 total files
Read source image "greenhouse_skybox-0.png", 1024x1024
Read source image "greenhouse_skybox-1.png", 1024x1024
Read source image "greenhouse_skybox-2.png", 1024x1024
Read source image "greenhouse_skybox-3.png", 1024x1024
Read source image "greenhouse_skybox-4.png", 1024x1024
Read source image "greenhouse_skybox-5.png", 1024x1024
Total basis file slices: 6
Slice: 0, alpha: 0, orig width/height: 1024x1024, width/height: 1024x1024, first_block: 0, image_index: 0, mip_level: 0
Slice: 1, alpha: 0, orig width/height: 1024x1024, width/height: 1024x1024, first_block: 65536, image_index: 1, mip_level: 0
Slice: 2, alpha: 0, orig width/height: 1024x1024, width/height: 1024x1024, first_block: 131072, image_index: 2, mip_level: 0
Slice: 3, alpha: 0, orig width/height: 1024x1024, width/height: 1024x1024, first_block: 196608, image_index: 3, mip_level: 0
Slice: 4, alpha: 0, orig width/height: 1024x1024, width/height: 1024x1024, first_block: 262144, image_index: 4, mip_level: 0
Slice: 5, alpha: 0, orig width/height: 1024x1024, width/height: 1024x1024, first_block: 327680, image_index: 5, mip_level: 0
Wrote output .basis file "cubemap.basis"
Compression succeeded to file "cubemap.basis" in 8.616 secs

I then run basis to unpack the file
basisu cubemap.basis

Output:

Basis Universal GPU Texture Compressor Reference Encoder v1.07.00, Copyright (C) 2017-2019 Binomial LLC, All rights reserved
Input file "cubemap.basis"
File version and CRC checks succeeded
File info:
  Version: 13
  Total header size: 215
  Total selectors: 2646
  Selector codebook size: 5055
  Total endpoints: 1359
  Endpoint codebook size: 2270
  Tables size: 1326
  Slices size: 473232
  Texture type: cubemap array
  us per frame: 0 (0.000000 fps)
  Total slices: 6
  Total images: 6
  Y Flipped: 0, Has alpha slices: 0
  userdata0: 0x0 userdata1: 0x0
  Per-image mipmap levels: 1 1 1 1 1 1 

Image info:
Image 0: MipLevels: 1 OrigDim: 1024x1024, BlockDim: 256x256, FirstSlice: 0, HasAlpha: 0
Image 1: MipLevels: 1 OrigDim: 1024x1024, BlockDim: 256x256, FirstSlice: 1, HasAlpha: 0
Image 2: MipLevels: 1 OrigDim: 1024x1024, BlockDim: 256x256, FirstSlice: 2, HasAlpha: 0
Image 3: MipLevels: 1 OrigDim: 1024x1024, BlockDim: 256x256, FirstSlice: 3, HasAlpha: 0
Image 4: MipLevels: 1 OrigDim: 1024x1024, BlockDim: 256x256, FirstSlice: 4, HasAlpha: 0
Image 5: MipLevels: 1 OrigDim: 1024x1024, BlockDim: 256x256, FirstSlice: 5, HasAlpha: 0

Transcode of image 0 level 0 res 1024x1024 format ETC1 succeeded
Transcode of image 0 level 0 res 1024x1024 format BC1 succeeded
Transcode of image 0 level 0 res 1024x1024 format BC4 succeeded
Transcode of image 0 level 0 res 1024x1024 format PVRTC1_4_OPAQUE_ONLY succeeded
Transcode of image 0 level 0 res 1024x1024 format BC7_M6_OPAQUE_ONLY succeeded
Transcode of image 0 level 0 res 1024x1024 format ETC2 succeeded
Transcode of image 0 level 0 res 1024x1024 format BC3 succeeded
Transcode of image 0 level 0 res 1024x1024 format BC5 succeeded
Transcode of image 1 level 0 res 1024x1024 format ETC1 succeeded
Transcode of image 1 level 0 res 1024x1024 format BC1 succeeded
Transcode of image 1 level 0 res 1024x1024 format BC4 succeeded
Transcode of image 1 level 0 res 1024x1024 format PVRTC1_4_OPAQUE_ONLY succeeded
Transcode of image 1 level 0 res 1024x1024 format BC7_M6_OPAQUE_ONLY succeeded
Transcode of image 1 level 0 res 1024x1024 format ETC2 succeeded
Transcode of image 1 level 0 res 1024x1024 format BC3 succeeded
Transcode of image 1 level 0 res 1024x1024 format BC5 succeeded
Transcode of image 2 level 0 res 1024x1024 format ETC1 succeeded
Transcode of image 2 level 0 res 1024x1024 format BC1 succeeded
Transcode of image 2 level 0 res 1024x1024 format BC4 succeeded
Transcode of image 2 level 0 res 1024x1024 format PVRTC1_4_OPAQUE_ONLY succeeded
Transcode of image 2 level 0 res 1024x1024 format BC7_M6_OPAQUE_ONLY succeeded
Transcode of image 2 level 0 res 1024x1024 format ETC2 succeeded
Transcode of image 2 level 0 res 1024x1024 format BC3 succeeded
Transcode of image 2 level 0 res 1024x1024 format BC5 succeeded
Transcode of image 3 level 0 res 1024x1024 format ETC1 succeeded
Transcode of image 3 level 0 res 1024x1024 format BC1 succeeded
Transcode of image 3 level 0 res 1024x1024 format BC4 succeeded
Transcode of image 3 level 0 res 1024x1024 format PVRTC1_4_OPAQUE_ONLY succeeded
Transcode of image 3 level 0 res 1024x1024 format BC7_M6_OPAQUE_ONLY succeeded
Transcode of image 3 level 0 res 1024x1024 format ETC2 succeeded
Transcode of image 3 level 0 res 1024x1024 format BC3 succeeded
Transcode of image 3 level 0 res 1024x1024 format BC5 succeeded
Transcode of image 4 level 0 res 1024x1024 format ETC1 succeeded
Transcode of image 4 level 0 res 1024x1024 format BC1 succeeded
Transcode of image 4 level 0 res 1024x1024 format BC4 succeeded
Transcode of image 4 level 0 res 1024x1024 format PVRTC1_4_OPAQUE_ONLY succeeded
Transcode of image 4 level 0 res 1024x1024 format BC7_M6_OPAQUE_ONLY succeeded
Transcode of image 4 level 0 res 1024x1024 format ETC2 succeeded
Transcode of image 4 level 0 res 1024x1024 format BC3 succeeded
Transcode of image 4 level 0 res 1024x1024 format BC5 succeeded
Transcode of image 5 level 0 res 1024x1024 format ETC1 succeeded
Transcode of image 5 level 0 res 1024x1024 format BC1 succeeded
Transcode of image 5 level 0 res 1024x1024 format BC4 succeeded
Transcode of image 5 level 0 res 1024x1024 format PVRTC1_4_OPAQUE_ONLY succeeded
Transcode of image 5 level 0 res 1024x1024 format BC7_M6_OPAQUE_ONLY succeeded
Transcode of image 5 level 0 res 1024x1024 format ETC2 succeeded
Transcode of image 5 level 0 res 1024x1024 format BC3 succeeded
Transcode of image 5 level 0 res 1024x1024 format BC5 succeeded
Wrote KTX file "cubemap_transcoded_cubemap_ETC1_0.ktx"
Wrote PNG file "cubemap_unpacked_rgb_ETC1_0_0.png"
Wrote PNG file "cubemap_unpacked_rgb_ETC1_1_0.png"
Wrote PNG file "cubemap_unpacked_rgb_ETC1_2_0.png"
Wrote PNG file "cubemap_unpacked_rgb_ETC1_3_0.png"
Wrote PNG file "cubemap_unpacked_rgb_ETC1_4_0.png"
Wrote PNG file "cubemap_unpacked_rgb_ETC1_5_0.png"
Wrote KTX file "cubemap_transcoded_cubemap_BC1_0.ktx"
Wrote PNG file "cubemap_unpacked_rgb_BC1_0_0.png"
Wrote PNG file "cubemap_unpacked_rgb_BC1_1_0.png"
Wrote PNG file "cubemap_unpacked_rgb_BC1_2_0.png"
Wrote PNG file "cubemap_unpacked_rgb_BC1_3_0.png"
Wrote PNG file "cubemap_unpacked_rgb_BC1_4_0.png"
Wrote PNG file "cubemap_unpacked_rgb_BC1_5_0.png"
Wrote KTX file "cubemap_transcoded_cubemap_BC4_0.ktx"
Wrote PNG file "cubemap_unpacked_rgb_BC4_0_0.png"
Wrote PNG file "cubemap_unpacked_rgb_BC4_1_0.png"
Wrote PNG file "cubemap_unpacked_rgb_BC4_2_0.png"
Wrote PNG file "cubemap_unpacked_rgb_BC4_3_0.png"
Wrote PNG file "cubemap_unpacked_rgb_BC4_4_0.png"
Wrote PNG file "cubemap_unpacked_rgb_BC4_5_0.png"
Wrote KTX file "cubemap_transcoded_cubemap_PVRTC1_4_OPAQUE_ONLY_0.ktx"
Wrote PNG file "cubemap_unpacked_rgb_PVRTC1_4_OPAQUE_ONLY_0_0.png"
Wrote PNG file "cubemap_unpacked_rgb_PVRTC1_4_OPAQUE_ONLY_1_0.png"
Wrote PNG file "cubemap_unpacked_rgb_PVRTC1_4_OPAQUE_ONLY_2_0.png"
Wrote PNG file "cubemap_unpacked_rgb_PVRTC1_4_OPAQUE_ONLY_3_0.png"
Wrote PNG file "cubemap_unpacked_rgb_PVRTC1_4_OPAQUE_ONLY_4_0.png"
Wrote PNG file "cubemap_unpacked_rgb_PVRTC1_4_OPAQUE_ONLY_5_0.png"
Wrote KTX file "cubemap_transcoded_cubemap_BC7_M6_OPAQUE_ONLY_0.ktx"
Wrote PNG file "cubemap_unpacked_rgb_BC7_M6_OPAQUE_ONLY_0_0.png"
Wrote PNG file "cubemap_unpacked_rgb_BC7_M6_OPAQUE_ONLY_1_0.png"
Wrote PNG file "cubemap_unpacked_rgb_BC7_M6_OPAQUE_ONLY_2_0.png"
Wrote PNG file "cubemap_unpacked_rgb_BC7_M6_OPAQUE_ONLY_3_0.png"
Wrote PNG file "cubemap_unpacked_rgb_BC7_M6_OPAQUE_ONLY_4_0.png"
Wrote PNG file "cubemap_unpacked_rgb_BC7_M6_OPAQUE_ONLY_5_0.png"
Wrote KTX file "cubemap_transcoded_cubemap_ETC2_0.ktx"
Wrote PNG file "cubemap_unpacked_rgb_ETC2_0_0.png"
Wrote PNG file "cubemap_unpacked_a_ETC2_0_0.png"
Wrote PNG file "cubemap_unpacked_rgb_ETC2_1_0.png"
Wrote PNG file "cubemap_unpacked_a_ETC2_1_0.png"
Wrote PNG file "cubemap_unpacked_rgb_ETC2_2_0.png"
Wrote PNG file "cubemap_unpacked_a_ETC2_2_0.png"
Wrote PNG file "cubemap_unpacked_rgb_ETC2_3_0.png"
Wrote PNG file "cubemap_unpacked_a_ETC2_3_0.png"
Wrote PNG file "cubemap_unpacked_rgb_ETC2_4_0.png"
Wrote PNG file "cubemap_unpacked_a_ETC2_4_0.png"
Wrote PNG file "cubemap_unpacked_rgb_ETC2_5_0.png"
Wrote PNG file "cubemap_unpacked_a_ETC2_5_0.png"
Wrote KTX file "cubemap_transcoded_cubemap_BC3_0.ktx"
Wrote PNG file "cubemap_unpacked_rgb_BC3_0_0.png"
Wrote PNG file "cubemap_unpacked_a_BC3_0_0.png"
Wrote PNG file "cubemap_unpacked_rgb_BC3_1_0.png"
Wrote PNG file "cubemap_unpacked_a_BC3_1_0.png"
Wrote PNG file "cubemap_unpacked_rgb_BC3_2_0.png"
Wrote PNG file "cubemap_unpacked_a_BC3_2_0.png"
Wrote PNG file "cubemap_unpacked_rgb_BC3_3_0.png"
Wrote PNG file "cubemap_unpacked_a_BC3_3_0.png"
Wrote PNG file "cubemap_unpacked_rgb_BC3_4_0.png"
Wrote PNG file "cubemap_unpacked_a_BC3_4_0.png"
Wrote PNG file "cubemap_unpacked_rgb_BC3_5_0.png"
Wrote PNG file "cubemap_unpacked_a_BC3_5_0.png"
Wrote KTX file "cubemap_transcoded_cubemap_BC5_0.ktx"
Wrote PNG file "cubemap_unpacked_rgb_BC5_0_0.png"
Wrote PNG file "cubemap_unpacked_rgb_BC5_1_0.png"
Wrote PNG file "cubemap_unpacked_rgb_BC5_2_0.png"
Wrote PNG file "cubemap_unpacked_rgb_BC5_3_0.png"
Wrote PNG file "cubemap_unpacked_rgb_BC5_4_0.png"
Wrote PNG file "cubemap_unpacked_rgb_BC5_5_0.png"
Success

However if I load one of the KTX files (e.g. cubemap_transcoded_cubemap_ETC2_0.ktx) using libktx, ktxTexture_CreateFromNamedFile with KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, libktx returns KTX_FILE_UNEXPECTED_EOF.

On inspection it appears as if, despite “numFaces” being 6 in the KTX file, only a single face image is present in the file. Similar results are seen using ktxTexture_GLUpload.

I have tried adding -tex_type cubemap to the unpack call but that didn't change the output.

Output from a libktx-based tool run on cubemap_transcoded_cubemap_ETC2_0.ktx shows the following header data. dataSize does imply there’s just one face image in the KTX.

----------------------------------------------------------------
|         Field        |   Dec   |    Hex   |       Enum       |
----------------------------------------------------------------
| glFormat             |       0 |      0x0 | <unknown>        |
| glInternalformat     |   36196 |   0x8d64 | GL_ETC1_RGB8_OES |
| glBaseInternalformat |    6407 |   0x1907 | GL_RGB           |
| glType               |       0 |      0x0 | <unknown>        |
| isArray              |       0 |      0x0 |                  |
| isCubemap            |       1 |      0x1 |                  |
| isCompressed         |       1 |      0x1 |                  |
| generateMipmaps      |       0 |      0x0 |                  |
| baseWidth            |    1024 |    0x400 |                  |
| baseHeight           |    1024 |    0x400 |                  |
| baseDepth            |       1 |      0x1 |                  |
| numDimensions        |       2 |      0x2 |                  |
| numLevels            |       1 |      0x1 |                  |
| numLayers            |       1 |      0x1 |                  |
| numFaces             |       6 |      0x6 |                  |
| kvDataLen            |       0 |      0x0 |                  |
| dataSize             | 3145728 | 0x300000 |                  |
----------------------------------------------------------------

Could you either check my use of the tool, or comment on the suggestion there might be a problem with basisu generating KTX files with numFaces set to 6 but only one face image in the file.

Jim

@jimblackler
Copy link
Author

jimblackler commented Jun 20, 2019

It now looks like there's a difference between Basis interpretation of KTX format and Khronos' interpretation in libktx (and PVRTexTool interpretation).

I had thought that Basis was only writing one image per cubemap. However having debugged the unpack process, I can see it is writing six images.

However, libktx inerprets the 32 bit value before each texture as being the number of bytes per image (“faceLodSize” here https://github.com/KhronosGroup/KTX-Software/blob/master/lib/texture.c#L958)

Basis on the other hand writes that value having multiplied the bytes per image by the number of faces https://github.com/BinomialLLC/basis_universal/blob/master/basisu_gpu_texture.cpp#L689

This is the format used in Khronos' own example cubemap KTX files, e.g. cubemap_yokohama_etc2_unorm.ktx

The KTX spec says

For most textures imageSize is the number of bytes of pixel data in the current LOD level. This includes all array layers, all z slices, all faces, all rows (or rows of blocks) and all pixels (or blocks) in each row for the mipmap level. It does not include any bytes in mipPadding.

The exception is non-array cubemap textures (any texture where numberOfFaces is 6 and numberOfArrayElements is 0). For these textures imageSize is the number of bytes in each face of the texture for the current LOD level, not including bytes in cubePadding or mipPadding.

This difference in interpretation results in libktx returning KTX_FILE_UNEXPECTED_EOF when it tries to read the data; it is reading 6x the data per image.

I've an experimental fix to Basis (move the img_sze = img_size * header.m_numberOfFaces ... to after the array_index loop in create_ktx_texture_file) and the resulting KTX files now load correctly both in libktx and PVRTexTool.

@jimblackler jimblackler changed the title Example command lines for creating a cubemap? imageSize set incorrectly for unpacked cubemaps Jun 20, 2019
jimblackler pushed a commit to jimblackler/basis_universal that referenced this issue Jun 20, 2019
@richgel999
Copy link
Contributor

Hi - Yea, this looks like a bug. I wrote a KTX reader/writer class a few years ago, and did this the way you and the standard describe.

@richgel999
Copy link
Contributor

I've checked in a fix for this:
c9d2411

Please let me know if this doesn't fix the problem. I tested with PVRTexTool, and it still loads the cubemap .ktx files written with basisu.exe okay.

@jimblackler
Copy link
Author

Thanks Rich. With your patch the assertion at line 709 fails

assert(bytes_written == img_size);

See my pull request for how I handled it.

@richgel999
Copy link
Contributor

Whoops! I made that fix half asleep, and missed that. I've checked in a fix (I just removed the assert).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants