-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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
Compressed texture support #3608
Comments
True, although I don't see that as a reason to rule it out as something supported at runtime. There are (very niche) edge cases where the build-time asset pipeline doesn't get a look-in, e.g. runtime-procedurally-generated content or user-supplied images. |
Has there been thought about assets that work on both desktop and mobile? The former typically only supports BC compression and while the latter supports ETC2 and ASTC, but almost never BC. The trendy approach at this point is to store assets in Basis format, and then transcode them at runtime to whatever compressed format is required. KTX2 actually supports Basis, so perhaps this is planned? |
At this point I'm basically of the opinion that basis doesn't provide much over just doing 2/3 encodings for the various formats. Not only do you don't have the chance to use more interesting formats like bc6h, bc4/5, eac, and hdr astc, but there's a quality hit and it requires a cpu side decode step, which isn't slow, but isn't terribly fast either, especially compared to being able to pull GB/s out of compressed textures. Every build only has to ship with one "kind" of assets, the exception being web, and you can still just pull the relevant platform assets based on what the device supports. Because od this I'm very disillusioned by basis and the only kind of supercompression I might use is simple zstd, but that likely should happen at the asset bundle level anyway. |
I started looking into adding ktx2 support using the |
I've pushed basic (not super-compressed) KTX2 support. I think support for supercompression should be a separate issue as it's a deeper rabbit hole. I think next I'll refactor it a bit (too much stuff in image.rs) and then look into properly handling the 2-component normal maps. |
Did you confirm that feeding the level data through a zstd decompressor doesn't work? A quick glance at the spec suggests that for Zstd and ZLIB compression that might just be all you need. (BasisLZ super compression on the other hand looks way more involved and almost certainly not worth worrying about now...) Totally understand putting this off for later though! |
I inspected the bytes of the levels and I think I fed them into zstd but I’m not totally sure. I’ll give it another go as for a while I was using the wrong data handle so it’s worth checking. I also looked at the spec and it looked like it is intended that each mip level is individually compressed by the supercompression technique. But there is also some supercompression global data that isn’t yet parsed in the ktx2 crate and I don’t know what is in that. I can take a look at the sample file I found in a Khronos repo too to see what’s in that. I’m thinking that it could be zstd metadata that needs to be used to configure the zstd decompressor before feeding it a mip level. |
It seems the supercompression global data for Zstandard is empty (0-byte length) and indeed shovelling the individual mip levels through Zstandard decompression does work (in the sense that it decompresses without errors.) However, I think parsing of the data format description part of the KTX2 metadata is necessary to discover the format of the supercompressed data. |
I've got basic parsing of the Data Format Description working, but the file I'm looking at has all UASTC format textures so I can't just load them directly. I'll either have to see if I can hook up a UASTC -> supported format transcoder or find a file which uses plain BC* or so. Maybe I could convert the dds texture version of bistro to ktx2... I expect there are tools around to do that. |
I have just finished implementing a hopefully reasonably correct mapping of ktx2 data format descriptor to wgpu texture formats where supported. It may not be 100% correct in the sense that maybe it could map some overlapping format to a wgpu format that it shouldn't, however unlikely this may be. I still need to add zlib decompression support, and then try to verify how well this works in practice by gathering a bunch of ktx2 files that contain raw or standard-compressed image data, not 'universal' compressed image data like ETC1S or UASTC. Then get a PR in shape against the |
Here is the |
I've got transcoding from UASTC from KTX2 files to appropriate formats (I tried BC7 and BC4, the latter for fun) using the |
I also made the various formats optional and non-default so people can pick and choose what they want/need to build in. |
Here's a PR for the exposing the so-called 'low-level' UASTC transcoder in |
I've implemented respecting the supported compressed formats when loading images, as reported by wgpu. So if a GPU-supported format (BC/ASTC/ETC2) is not supported by the GPU, an error should communicate that. And if loading a universal format like ETC1S/UASTC, the supported formats are used to identify to what GPU-supported compressed format we should transcode. I had previously written that we could implement a fallback to decompress the compressed format. I have implemented that for UASTC/ETC1S universal formats so they will fall back to RGBA32. I don't think this is trivial to implement for other cases. |
The The Along the way I was enlightened that M1 GPUs support ASTC / BC / EAC/ETC2 / PVRTC (so pretty much everything) also on macOS but that wgpu was only reporting support for BC. I filed an issue here but dug into it some more and ended up making a PR here. Once |
A new version of I added support for 2-component normal map textures through a standard material flag. |
I made a draft pull request: #3884 |
# Objective - Support compressed textures including 'universal' formats (ETC1S, UASTC) and transcoding of them to - Support `.dds`, `.ktx2`, and `.basis` files ## Solution - Fixes bevyengine#3608 Look there for more details. - Note that the functionality is all enabled through non-default features. If it is desirable to enable some by default, I can do that. - The `basis-universal` crate, used for `.basis` file support and for transcoding, is built on bindings against a C++ library. It's not feasible to rewrite in Rust in a short amount of time. There are no Rust alternatives of which I am aware and it's specialised code. In its current state it doesn't support the wasm target, but I don't know for sure. However, it is possible to build the upstream C++ library with emscripten, so there is perhaps a way to add support for web too with some shenanigans. - There's no support for transcoding from BasisLZ/ETC1S in KTX2 files as it was quite non-trivial to implement and didn't feel important given people could use `.basis` files for ETC1S.
# Objective - Support compressed textures including 'universal' formats (ETC1S, UASTC) and transcoding of them to - Support `.dds`, `.ktx2`, and `.basis` files ## Solution - Fixes bevyengine#3608 Look there for more details. - Note that the functionality is all enabled through non-default features. If it is desirable to enable some by default, I can do that. - The `basis-universal` crate, used for `.basis` file support and for transcoding, is built on bindings against a C++ library. It's not feasible to rewrite in Rust in a short amount of time. There are no Rust alternatives of which I am aware and it's specialised code. In its current state it doesn't support the wasm target, but I don't know for sure. However, it is possible to build the upstream C++ library with emscripten, so there is perhaps a way to add support for web too with some shenanigans. - There's no support for transcoding from BasisLZ/ETC1S in KTX2 files as it was quite non-trivial to implement and didn't feel important given people could use `.basis` files for ETC1S.
# Objective - Support compressed textures including 'universal' formats (ETC1S, UASTC) and transcoding of them to - Support `.dds`, `.ktx2`, and `.basis` files ## Solution - Fixes bevyengine/bevy#3608 Look there for more details. - Note that the functionality is all enabled through non-default features. If it is desirable to enable some by default, I can do that. - The `basis-universal` crate, used for `.basis` file support and for transcoding, is built on bindings against a C++ library. It's not feasible to rewrite in Rust in a short amount of time. There are no Rust alternatives of which I am aware and it's specialised code. In its current state it doesn't support the wasm target, but I don't know for sure. However, it is possible to build the upstream C++ library with emscripten, so there is perhaps a way to add support for web too with some shenanigans. - There's no support for transcoding from BasisLZ/ETC1S in KTX2 files as it was quite non-trivial to implement and didn't feel important given people could use `.basis` files for ETC1S.
Description
Solution
create_texture_with_data
toRenderDevice
and using itGpuImage
, if it is a compressed format, useRenderDevice::create_texture_with_data
with the specified format, which includes all mipmaps. If it is not compressed, copy mipmap level 0 only as before.CompressedImageFormats
flag type withASTC_LDR
,BC
, andETC2
flags to match what is supported bywgpu::Features
supported_compressed_formats
member toImageTextureLoader
andGltfLoader
and populate it based onWgpuOptions
at loader-initialisation-time.Image
usingImage::from_buffer()
, pass theCompressedImageFormats
stored in the loader to inform the load() about whether compressed formats are supported, and/or about formats to transcode to, in case of universal compressed formats such as UASTC/ETC1S.ddsfile
crate, intoImage
and set the correct image format. Note that this includes all mipmaps.ktx2
crate, intoImage
and set the correct image format. Note that this includes all mipmaps.flate2
which in turn usesminiz_oxide
which is a rust DEFLATE implementationruzstd
which is a rust Zstandard decompressorbasis-universal
crate which uses bindings to the C++ Basis Universal library.basis
file support for ETC1S/UASTC with transcoding to an appropriate format, also using thebasis-universal
crateNext Steps
.basis
files and transcoding UASTC from KTX2 files. The basis-universal library has been compiled to WASM. It is possible to call other JavaScript code from rust code compiled to WASM using C-style FFI so maybe it will work for WASM to WASM as well?.basis
files to start with.The text was updated successfully, but these errors were encountered: