-
Notifications
You must be signed in to change notification settings - Fork 2k
Open
Description
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);
}
Metadata
Metadata
Assignees
Labels
No labels