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

Wrong calculation of DDS texture mipmap sizes #3375

Open
d1str4ught opened this issue Nov 12, 2024 · 1 comment
Open

Wrong calculation of DDS texture mipmap sizes #3375

d1str4ught opened this issue Nov 12, 2024 · 1 comment

Comments

@d1str4ught
Copy link

I try to load DDS files with mipmaps, but when I create textures from them, it fails because of the mipmaps.
I used the bimg loader first, did not work, then I used https://github.com/septag/dds-ktx library.
My implementation is below.
So when I call createTexture2D, the assertion below fails:

		if (BX_ENABLED(BGFX_CONFIG_DEBUG)
		&&  NULL != _mem)
		{
			TextureInfo ti;
			calcTextureSize(ti, _width, _height, 1, false, _hasMips, _numLayers, _format);
			BX_ASSERT(ti.storageSize == _mem->size
				, "createTexture2D: Texture storage size doesn't match passed memory size (storage size: %d, memory size: %d)"
				, ti.storageSize
				, _mem->size
				);
		}

storageSize is grater then _mem->size.
I tried to debug it, and I found out that that calcTextureSize will yield a different size for around the 6th mipmap.
bimg::calcTextureSize: 37888 + 9728 + 2560 + 640 + 192 + 64
my calculation: 37888 + 9728 + 2560 + 640 + 192 + 32

Because of this, mipmaps are misaligned in memory causing strange looking textures in the game.

Here is my implementation:

#include <bgfx/platform.h>
#include <bx/file.h>
#include <bx/readerwriter.h>
#include <bx/math.h>
#include <bx/os.h>

#define DDSKTX_IMPLEMENT
#include <dds-ktx.h>

bool LoadDDSFromMemory(const uint8_t* ddsData, size_t ddsDataSize, bgfx::TextureHandle& texture, bgfx::TextureInfo& info)
{
    ddsktx_texture_info textureInfo = { 0 };
    if (!ddsktx_parse(&textureInfo, ddsData, ddsDataSize, NULL)) {
        return false;
    }

    info.format = bgfx::TextureFormat::Unknown;
    info.width = textureInfo.width;
    info.height = textureInfo.height;

    switch (textureInfo.format)
    {
        case DDSKTX_FORMAT_BC1:
            info.format = bgfx::TextureFormat::BC1;
            break;
        case DDSKTX_FORMAT_BC2:
            info.format = bgfx::TextureFormat::BC2;
            break;
        case DDSKTX_FORMAT_BC3:
            info.format = bgfx::TextureFormat::BC3;
            break;
        case DDSKTX_FORMAT_BC6H:
            info.format = bgfx::TextureFormat::BC6H;
            break;
        case DDSKTX_FORMAT_BC7:
            info.format = bgfx::TextureFormat::BC7;
            break;
        case DDSKTX_FORMAT_RGBA8:
            info.format = bgfx::TextureFormat::RGBA8;
            break;

        default:
            return false;
    }

    // Calculate total size for all mip levels
    uint32_t totalSize = 0;
    for (uint32_t mip = 0; mip < textureInfo.num_mips; mip++)
    {
        ddsktx_sub_data sub_data;
        ddsktx_get_sub(&textureInfo, &sub_data, ddsData, ddsDataSize, 0, 0, mip);
        totalSize += static_cast<uint32_t>(sub_data.size_bytes);
    }

    // Allocate memory
    const bgfx::Memory* mem = bgfx::alloc(totalSize);

    // Copy mip levels
    uint8_t* dest = mem->data;
    for (uint32_t mip = 0; mip < textureInfo.num_mips; mip++)
    {
        ddsktx_sub_data sub_data;
        ddsktx_get_sub(&textureInfo, &sub_data, ddsData, ddsDataSize, 0, 0, mip);
        memcpy(dest, sub_data.buff, sub_data.size_bytes);
        dest += sub_data.size_bytes;
    }

    // Create texture
    texture = bgfx::createTexture2D(
        static_cast<uint16_t>(textureInfo.width),
        static_cast<uint16_t>(textureInfo.height),
        textureInfo.num_mips > 1,
        textureInfo.num_layers,
        info.format,
        BGFX_TEXTURE_NONE,
        mem
    );

    return bgfx::isValid(texture);
}
@bkaradzic
Copy link
Owner

Attach .dds that is not loading.

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

No branches or pull requests

2 participants