Skip to content

Commit 2a7f67f

Browse files
committed
KTX2Loader: Fix ETC1S/UASTC prioritization
Due to a historical accident, the list of formats for ETC1S was sorted using UASTC priority. This change fixes that. However, this exposes a problem that already exists for UASTC to ETC1S as well: on Linux, Mesa drivers for various Intel and AMD GPUs expose support for ETC2 and ASTC extensions even if the hardware does not support them, as part of GLES compatibility. When a texture with an emulated format is uploaded, the driver runs a very expensive CPU side decompression; this runs on the main thread and causes performance and memory issues. When using Chrome based browsers, ANGLE filters out ASTC and ETC extensions for us; we now detect Gecko based browsers like Firefox that don't use ANGLE and do this filtering ourselves. In principle, it is possible for GPUs to support all formats - notably, Safari exposes all formats on macOS when using Apple Silicon hardware, as it genuinely supports all possible formats. In this case we still should prefer native (ASTC/ETC2) format targets as they are faster to transcode to. A corner case is a combination of Firefox / Asahi Linux on Apple Silicon hardware; in the future it might be possible to detect the unmasked vendor to disambiguate, but even that combination will simply use BC7 for UASTC or dual-slice ETC1S which is probably reasonable.
1 parent d47d1d8 commit 2a7f67f

File tree

1 file changed

+17
-6
lines changed

1 file changed

+17
-6
lines changed

examples/jsm/loaders/KTX2Loader.js

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ class KTX2Loader extends Loader {
189189
* Async version of {@link KTX2Loader#detectSupport}.
190190
*
191191
* @async
192-
* @param {WebGPURenderer|WebGLRenderer} renderer - The renderer.
192+
* @param {WebGPURenderer} renderer - The renderer.
193193
* @return {Promise} A Promise that resolves when the support has been detected.
194194
*/
195195
async detectSupportAsync( renderer ) {
@@ -242,6 +242,21 @@ class KTX2Loader extends Loader {
242242
pvrtcSupported: renderer.extensions.has( 'WEBGL_compressed_texture_pvrtc' )
243243
|| renderer.extensions.has( 'WEBKIT_WEBGL_compressed_texture_pvrtc' )
244244
};
245+
246+
if ( typeof navigator !== 'undefined' &&
247+
navigator.platform.indexOf( 'Linux' ) >= 0 && navigator.userAgent.indexOf( 'Firefox' ) >= 0 &&
248+
this.workerConfig.astcSupported && this.workerConfig.etc2Supported &&
249+
this.workerConfig.bptcSupported && this.workerConfig.dxtSupported ) {
250+
251+
// On Linux, Mesa drivers for AMD and Intel GPUs expose ETC2 and ASTC even though the hardware doesn't support these.
252+
// Using these extensions will result in expensive software decompression on the main thread inside the driver, causing performance issues.
253+
// When using ANGLE (e.g. via Chrome), these extensions are not exposed except for some specific Intel GPU models - however, Firefox doesn't perform this filtering.
254+
// Since a granular filter is a little too fragile and we can transcode into other GPU formats, disable formats that are likely to be emulated.
255+
256+
this.workerConfig.astcSupported = false;
257+
this.workerConfig.etc2Supported = false;
258+
259+
}
245260

246261
}
247262

@@ -841,13 +856,9 @@ KTX2Loader.BasisWorker = function () {
841856
];
842857

843858
const OPTIONS = {
844-
// TODO: For ETC1S we intentionally sort by _UASTC_ priority, preserving
845-
// a historical accident shown to avoid performance pitfalls for Linux with
846-
// Firefox & AMD GPU (RadeonSI). Further work needed.
847-
// See https://github.com/mrdoob/three.js/pull/29730.
848859
[ BasisFormat.ETC1S ]: FORMAT_OPTIONS
849860
.filter( ( opt ) => opt.basisFormat.includes( BasisFormat.ETC1S ) )
850-
.sort( ( a, b ) => a.priorityUASTC - b.priorityUASTC ),
861+
.sort( ( a, b ) => a.priorityETC1S - b.priorityETC1S ),
851862

852863
[ BasisFormat.UASTC ]: FORMAT_OPTIONS
853864
.filter( ( opt ) => opt.basisFormat.includes( BasisFormat.UASTC ) )

0 commit comments

Comments
 (0)