Просмотр исходного кода

KTX2Loader: Fix ETC1S/UASTC prioritization (#31871)

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.
Arseny Kapoulkine 7 месяцев назад
Родитель
Сommit
eac5acce91
1 измененных файлов с 17 добавлено и 6 удалено
  1. 17 6
      examples/jsm/loaders/KTX2Loader.js

+ 17 - 6
examples/jsm/loaders/KTX2Loader.js

@@ -194,7 +194,7 @@ class KTX2Loader extends Loader {
 	 * Async version of {@link KTX2Loader#detectSupport}.
 	 *
 	 * @async
-	 * @param {WebGPURenderer|WebGLRenderer} renderer - The renderer.
+	 * @param {WebGPURenderer} renderer - The renderer.
 	 * @return {Promise} A Promise that resolves when the support has been detected.
 	 */
 	async detectSupportAsync( renderer ) {
@@ -247,6 +247,21 @@ class KTX2Loader extends Loader {
 				pvrtcSupported: renderer.extensions.has( 'WEBGL_compressed_texture_pvrtc' )
 					|| renderer.extensions.has( 'WEBKIT_WEBGL_compressed_texture_pvrtc' )
 			};
+			
+			if ( typeof navigator !== 'undefined' &&
+				navigator.platform.indexOf( 'Linux' ) >= 0 && navigator.userAgent.indexOf( 'Firefox' ) >= 0 &&
+				this.workerConfig.astcSupported && this.workerConfig.etc2Supported && 
+				this.workerConfig.bptcSupported && this.workerConfig.dxtSupported ) {
+					
+				// On Linux, Mesa drivers for AMD and Intel GPUs expose ETC2 and ASTC even though the hardware doesn't support these.
+				// Using these extensions will result in expensive software decompression on the main thread inside the driver, causing performance issues.
+				// 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.
+				// 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.
+				
+				this.workerConfig.astcSupported = false;
+				this.workerConfig.etc2Supported = false;
+					
+			}
 
 		}
 
@@ -846,13 +861,9 @@ KTX2Loader.BasisWorker = function () {
 	];
 
 	const OPTIONS = {
-		// TODO: For ETC1S we intentionally sort by _UASTC_ priority, preserving
-		// a historical accident shown to avoid performance pitfalls for Linux with
-		// Firefox & AMD GPU (RadeonSI). Further work needed.
-		// See https://github.com/mrdoob/three.js/pull/29730.
 		[ BasisFormat.ETC1S ]: FORMAT_OPTIONS
 			.filter( ( opt ) => opt.basisFormat.includes( BasisFormat.ETC1S ) )
-			.sort( ( a, b ) => a.priorityUASTC - b.priorityUASTC ),
+			.sort( ( a, b ) => a.priorityETC1S - b.priorityETC1S ),
 
 		[ BasisFormat.UASTC ]: FORMAT_OPTIONS
 			.filter( ( opt ) => opt.basisFormat.includes( BasisFormat.UASTC ) )

粤ICP备19079148号