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

BasisUniversal: Use RGTC compression when available #90170

Merged
merged 1 commit into from
Sep 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 68 additions & 21 deletions modules/basis_universal/image_compress_basisu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,14 +84,12 @@ Vector<uint8_t> basis_universal_packer(const Ref<Image> &p_image, Image::UsedCha
decompress_format = BASIS_DECOMPRESS_RGBA;
} break;
case Image::USED_CHANNELS_R: {
decompress_format = BASIS_DECOMPRESS_RGB;
decompress_format = BASIS_DECOMPRESS_R;
} break;
case Image::USED_CHANNELS_RG: {
// Currently RG textures are compressed as DXT5/ETC2_RGBA8 with a RA -> RG swizzle,
// as BasisUniversal didn't use to support ETC2_RG11 transcoding.
params.m_force_alpha = true;
image->convert_rg_to_ra_rgba8();
decompress_format = BASIS_DECOMPRESS_RG_AS_RA;
decompress_format = BASIS_DECOMPRESS_RG;
} break;
case Image::USED_CHANNELS_RGB: {
decompress_format = BASIS_DECOMPRESS_RGB;
Expand Down Expand Up @@ -219,15 +217,68 @@ Ref<Image> basis_universal_unpacker_ptr(const uint8_t *p_data, int p_size) {
// Get supported compression formats.
bool bptc_supported = RS::get_singleton()->has_os_feature("bptc");
bool astc_supported = RS::get_singleton()->has_os_feature("astc");
bool rgtc_supported = RS::get_singleton()->has_os_feature("rgtc");
bool s3tc_supported = RS::get_singleton()->has_os_feature("s3tc");
bool etc2_supported = RS::get_singleton()->has_os_feature("etc2");

bool needs_ra_rg_swap = false;
bool needs_rg_trim = false;

BasisDecompressFormat decompress_format = (BasisDecompressFormat)(*(uint32_t *)(src_ptr));

switch (*(uint32_t *)(src_ptr)) {
switch (decompress_format) {
case BASIS_DECOMPRESS_R: {
if (rgtc_supported) {
basisu_format = basist::transcoder_texture_format::cTFBC4_R;
image_format = Image::FORMAT_RGTC_R;
} else if (s3tc_supported) {
basisu_format = basist::transcoder_texture_format::cTFBC1;
image_format = Image::FORMAT_DXT1;
} else if (etc2_supported) {
basisu_format = basist::transcoder_texture_format::cTFETC2_EAC_R11;
image_format = Image::FORMAT_ETC2_R11;
} else {
// No supported VRAM compression formats, decompress.
basisu_format = basist::transcoder_texture_format::cTFRGBA32;
image_format = Image::FORMAT_RGBA8;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't Image::FORMAT_R8 be used here?

needs_rg_trim = true;
}

} break;
case BASIS_DECOMPRESS_RG: {
// RGTC transcoding is currently performed with RG_AS_RA, fail.
ERR_FAIL_V(image);
if (rgtc_supported) {
basisu_format = basist::transcoder_texture_format::cTFBC5_RG;
image_format = Image::FORMAT_RGTC_RG;
} else if (s3tc_supported) {
basisu_format = basist::transcoder_texture_format::cTFBC3;
image_format = Image::FORMAT_DXT5_RA_AS_RG;
} else if (etc2_supported) {
basisu_format = basist::transcoder_texture_format::cTFETC2_EAC_RG11;
image_format = Image::FORMAT_ETC2_RG11;
} else {
// No supported VRAM compression formats, decompress.
basisu_format = basist::transcoder_texture_format::cTFRGBA32;
image_format = Image::FORMAT_RGBA8;
needs_ra_rg_swap = true;
needs_rg_trim = true;
}

} break;
case BASIS_DECOMPRESS_RG_AS_RA: {
if (s3tc_supported) {
basisu_format = basist::transcoder_texture_format::cTFBC3;
image_format = Image::FORMAT_DXT5_RA_AS_RG;
} else if (etc2_supported) {
basisu_format = basist::transcoder_texture_format::cTFETC2;
image_format = Image::FORMAT_ETC2_RA_AS_RG;
} else {
// No supported VRAM compression formats, decompress.
basisu_format = basist::transcoder_texture_format::cTFRGBA32;
image_format = Image::FORMAT_RGBA8;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't Image::FORMAT_RG8 or Image::FORMAT_LA8 be used here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BasisU doesn't allow directly decompressing textures to R8/RG8, so they have to be converted after decompression. This increases the loading time slightly, though I think the tradeoff is worth it since less VRAM is wasted.

needs_ra_rg_swap = true;
needs_rg_trim = true;
}

} break;
case BASIS_DECOMPRESS_RGB: {
if (bptc_supported) {
Expand Down Expand Up @@ -267,20 +318,7 @@ Ref<Image> basis_universal_unpacker_ptr(const uint8_t *p_data, int p_size) {
basisu_format = basist::transcoder_texture_format::cTFRGBA32;
image_format = Image::FORMAT_RGBA8;
}
} break;
case BASIS_DECOMPRESS_RG_AS_RA: {
if (s3tc_supported) {
basisu_format = basist::transcoder_texture_format::cTFBC3;
image_format = Image::FORMAT_DXT5_RA_AS_RG;
} else if (etc2_supported) {
basisu_format = basist::transcoder_texture_format::cTFETC2;
image_format = Image::FORMAT_ETC2_RA_AS_RG;
} else {
// No supported VRAM compression formats, decompress.
basisu_format = basist::transcoder_texture_format::cTFRGBA32;
image_format = Image::FORMAT_RGBA8;
needs_ra_rg_swap = true;
}

} break;
}

Expand Down Expand Up @@ -324,6 +362,15 @@ Ref<Image> basis_universal_unpacker_ptr(const uint8_t *p_data, int p_size) {
image->convert_ra_rgba8_to_rg();
}

if (needs_rg_trim) {
// Remove unnecessary color channels from uncompressed textures.
if (decompress_format == BASIS_DECOMPRESS_R) {
image->convert(Image::FORMAT_R8);
} else if (decompress_format == BASIS_DECOMPRESS_RG || decompress_format == BASIS_DECOMPRESS_RG_AS_RA) {
image->convert(Image::FORMAT_RG8);
}
}

return image;
}

Expand Down
1 change: 1 addition & 0 deletions modules/basis_universal/image_compress_basisu.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ enum BasisDecompressFormat {
BASIS_DECOMPRESS_RGB,
BASIS_DECOMPRESS_RGBA,
BASIS_DECOMPRESS_RG_AS_RA,
BASIS_DECOMPRESS_R,
};

void basis_universal_init();
Expand Down
Loading