diff --git a/common/src/main/java/io/homo/superresolution/common/gui/MaterialConfigScreen.java b/common/src/main/java/io/homo/superresolution/common/gui/MaterialConfigScreen.java index d961e64e..c8e3c8fc 100644 --- a/common/src/main/java/io/homo/superresolution/common/gui/MaterialConfigScreen.java +++ b/common/src/main/java/io/homo/superresolution/common/gui/MaterialConfigScreen.java @@ -521,6 +521,13 @@ private Frame createGeneralFrame() { .setText(Text.translatable("superresolution.screen.config.hint.performance_warning.text").getString()) .setDisplayRequirement(OptionRequirement.isTrue(() -> SuperResolutionConfig.isEnableUpscaleOriginal() && !SRWorkModeManager.getCurrentState().shaderPackInUse() && !SuperResolutionConfig.isDisableUpscaleOnVanilla())) .build(); + builder.hintOption(Text.literal("frame_generation_only_warning")) + .setIcon(MaterialSymbols.iconWarning()) + .setTitle(Text.translatable("superresolution.screen.config.hint.frame_generation_only_warning.title").getString()) + .setText(Text.translatable("superresolution.screen.config.hint.frame_generation_only_warning.text").getString()) + .setDisplayRequirement(OptionRequirement.isTrue(() -> + SRWorkModeManager.getCurrentState().onlySupportsFrameGeneration())) + .build(); builder.hintOption(Text.literal("shader_compat_warning")) .setIcon(MaterialSymbols.iconWarning()) .setTitle(Text.translatable("superresolution.screen.config.hint.shader_compat_warning.title").getString()) @@ -598,7 +605,8 @@ private Frame createGeneralFrame() { if (isExperimentalAlgorithm(algorithmDescription)) return SuperResolutionConfig.isEnableExperimentalFeatures(); return true; - } + }, + () -> !SRWorkModeManager.getCurrentState().disabledAlgorithms().contains(algorithmDescription.getCodeName()) ); }) .setMenuItemTooltipSupplier((algo)->{ @@ -606,6 +614,10 @@ private Frame createGeneralFrame() { var result = algorithmDescription.getRequirement().check(); StringBuilder sb = new StringBuilder(); sb.append(algorithmDescription.getDisplayName()); + if (SRWorkModeManager.getCurrentState().disabledAlgorithms().contains(algorithmDescription.getCodeName())) { + sb.append("\n"); + sb.append(Text.translatable("superresolution.screen.config.options.tooltip.algo.disabled_by_shaderpack").getString()); + } if (isExperimentalAlgorithm(algorithmDescription) && SuperResolutionConfig.isEnableExperimentalFeatures()){ sb.append("\n"); sb.append(Text.translatable("superresolution.screen.config.options.tooltip.algo.experimental_warning").getString()); diff --git a/common/src/main/java/io/homo/superresolution/common/workmode/SRWorkModeState.java b/common/src/main/java/io/homo/superresolution/common/workmode/SRWorkModeState.java index 190dd0b9..8b8ede85 100644 --- a/common/src/main/java/io/homo/superresolution/common/workmode/SRWorkModeState.java +++ b/common/src/main/java/io/homo/superresolution/common/workmode/SRWorkModeState.java @@ -4,12 +4,17 @@ import io.homo.superresolution.core.graphics.impl.texture.TextureFormat; import org.jetbrains.annotations.Nullable; +import java.util.Collections; +import java.util.List; + public record SRWorkModeState( InitializationDescription initializationDescription, TextureFormat internalTextureFormat, @Nullable String motionVectorPreprocessingFunction, boolean shaderPackInUse, - boolean shaderPackLoading + boolean shaderPackLoading, + boolean onlySupportsFrameGeneration, + List disabledAlgorithms ) { public static SRWorkModeState defaults() { return new SRWorkModeState( @@ -17,7 +22,9 @@ public static SRWorkModeState defaults() { TextureFormat.RGBA16F, null, false, - false + false, + false, + Collections.emptyList() ); } } diff --git a/common/src/main/resources/assets/super_resolution/lang/en_us.json b/common/src/main/resources/assets/super_resolution/lang/en_us.json index 29d8b3b7..4b894ba0 100644 --- a/common/src/main/resources/assets/super_resolution/lang/en_us.json +++ b/common/src/main/resources/assets/super_resolution/lang/en_us.json @@ -291,6 +291,7 @@ "superresolution.screen.warn": "Warning", "superresolution.screen.config.options.tooltip.algo.experimental_warning": "This algorithm is experimental, unstable, and may cause crashes or errors", "superresolution.screen.config.options.tooltip.algo.experimental_disabled_hint": "This algorithm is experimental, unstable, and may cause crashes or errors\nTo use it, please enable Experimental > Enable Experimental Features", + "superresolution.screen.config.options.tooltip.algo.disabled_by_shaderpack": "This algorithm is disabled by the shader pack", "superresolution.screen.config.options.tooltip.algo.unsupported_reason_header": "This algorithm is not supported. Reasons:", "superresolution.screen.config.options.tooltip.algo.reason.opengl_version": "· OpenGL version not supported", "superresolution.screen.config.options.tooltip.algo.reason.opengl_extension": "· Missing required OpenGL extensions", @@ -309,5 +310,7 @@ "superresolution.screen.config.hint.b3d_vulkan_unavailable.text": "The Vulkan graphics backend is currently in use. Because Iris does not support the Vulkan backend yet, Super Resolution cannot enable upscaling or scaling in this environment; you can still open the configuration screen, but all features will be unavailable.", "superresolution.screen.config.hint.shader_compat_warning.title": "Shader Compatibility Warning", "superresolution.screen.config.hint.shader_compat_warning.text": "The current shader pack has not been adapted for the super resolution mod and will run in compatibility mode. This mode may cause: blurry visuals, ghosting artifacts, performance degradation, and reduced compatibility with other mods.", + "superresolution.screen.config.hint.frame_generation_only_warning.title": "Frame Generation Only Mode", + "superresolution.screen.config.hint.frame_generation_only_warning.text": "This shader pack uses frame-generation-only mode. Super resolution is disabled.", "superresolution.translate.PoweredByDeepSeek": "Powered by DeepSeek" } diff --git a/common/src/main/resources/assets/super_resolution/lang/ja_jp.json b/common/src/main/resources/assets/super_resolution/lang/ja_jp.json index e4af50b6..646e41a0 100644 --- a/common/src/main/resources/assets/super_resolution/lang/ja_jp.json +++ b/common/src/main/resources/assets/super_resolution/lang/ja_jp.json @@ -62,8 +62,8 @@ "superresolution.screen.config.button.label.info": "情報", "superresolution.screen.config.category.debug": "デバッグ設定", "superresolution.screen.config.category.general": "一般", - "superresolution.screen.config.category.super_resolution": "超解像度", - "superresolution.screen.config.category.other": "その他", + "superresolution.screen.config.category.super_resolution": "超解像度", + "superresolution.screen.config.category.other": "その他", "superresolution.screen.config.category.advanced": "詳細", "superresolution.screen.config.category.appearance": "外観", "superresolution.screen.config.category.experimental": "実験的", @@ -98,7 +98,7 @@ "superresolution.screen.config.error.capture_mode_unsupported": "現在のキャプチャ方式は %s では使用できません。", "superresolution.screen.config.error.unsupported_algorithm": "現在の環境ではこのアルゴリズムはサポートされていません", "superresolution.screen.config.info.about.amd_disclaimer": "本ソフトウェアで言及される AMD は、Advanced Micro Devices, Inc. の米国およびその他の国における商標または登録商標です。本プロジェクトは Advanced Micro Devices, Inc. と一切関係がなく、同社による承認や認可も受けていません。", - "superresolution.screen.config.info.about.contributor.187j3x1.desc": "この人、たぶん作者です", + "superresolution.screen.config.info.about.contributor.187j3x1.desc": "この人、たぶん作者です", "superresolution.screen.config.info.about.contributor.ar.desc": "キツネ!キツネ!キツネ!", "superresolution.screen.config.info.about.contributor.chenmeng.desc": "天才(笑)", "superresolution.screen.config.info.about.contributor.chloeprime.desc": "このMODのバグ修正やその他の貢献に感謝します!", @@ -109,9 +109,9 @@ "superresolution.screen.config.info.about.contributor.shiroiame.desc": "このMODの多くのバグ修正や、その他の貢献に感謝します!", "superresolution.screen.config.info.about.contributor.suodeliesi.desc": "機材の提供や、Intel環境におけるいくつかのバグ修正に感謝します。", "superresolution.screen.config.info.about.contributor.starsshine11904.desc": "このMODの繁体字中国語翻訳を作成してくださり、ありがとうございます!", - "superresolution.screen.config.info.about.contributor.nohimazin.desc": "このMODの日本語翻訳を作成してくださり、ありがとうございます!", - "superresolution.screen.config.info.about.contributor.haringpro.desc": "Revoxelation/Revelation シェーダーに Super Resolution 互換性を追加してくださり、ありがとうございます!", - "superresolution.screen.config.info.about.contributor.tahnass.desc": "ITRP shadersにSuper Resolution対応を追加してくださり、ありがとうございます!", + "superresolution.screen.config.info.about.contributor.nohimazin.desc": "このMODの日本語翻訳を作成してくださり、ありがとうございます!", + "superresolution.screen.config.info.about.contributor.haringpro.desc": "Revoxelation/Revelation シェーダーに Super Resolution 互換性を追加してくださり、ありがとうございます!", + "superresolution.screen.config.info.about.contributor.tahnass.desc": "ITRP shadersにSuper Resolution対応を追加してくださり、ありがとうございます!", "superresolution.screen.config.info.about.contributor.geforcelegend.desc": "Sundial shadersにSuper Resolution対応を追加してくださり、ありがとうございます!", "superresolution.screen.config.info.about.contributor.xiaolang.desc": "RTX 5090 の寄付に感謝します!", "superresolution.screen.config.info.about.contributor.ysjmxy.desc": "謎のマスコット!", @@ -218,8 +218,8 @@ "superresolution.screen.config.section.performance.chart.world_render": "ワールドレンダラー", "superresolution.screen.config.section.performance.chart.gui": "GUI", "superresolution.screen.config.section.profiling": "プロファイラー", - "superresolution.screen.config.special.dlss.renderpreset.name": "NVIDIA DLSS レンダープリセット", - "superresolution.screen.config.special.dlss.renderpreset.tooltip": "NVIDIA DLSS のレンダープリセット(モデル)を選択します", + "superresolution.screen.config.special.dlss.renderpreset.name": "NVIDIA DLSS レンダープリセット", + "superresolution.screen.config.special.dlss.renderpreset.tooltip": "NVIDIA DLSS のレンダープリセット(モデル)を選択します", "superresolution.screen.config.special.fsr.version.name": "FSR バージョン", "superresolution.screen.config.special.fsr.version.tooltip": "FSR のバージョン: 2.3.3 は FSR2 で、3.1.4 は FSR3 です。\n既定は 2.3.3 です", "superresolution.screen.config.special.fsr1.fp16.name": "半精度 (FP16) を有効化", @@ -238,17 +238,17 @@ "superresolution.screen.info.button.label.opengl_ext_info": "OpenGL 拡張情報", "superresolution.screen.info.button.label.vulkan_ext_info": "Vulkan 拡張情報", "superresolution.screen.info.link.github_repo": "GitHub リポジトリ", - "superresolution.screen.info.link.issue_tracker": "問題追跡", - "superresolution.screen.info.link.mcmod_homepage": "MC百科のホームページ", - "superresolution.screen.info.link.official_website": "公式サイト", - "superresolution.screen.info.link.wiki": "Wiki", - "superresolution.screen.info.name": "情報", + "superresolution.screen.info.link.issue_tracker": "問題追跡", + "superresolution.screen.info.link.mcmod_homepage": "MC百科のホームページ", + "superresolution.screen.info.link.official_website": "公式サイト", + "superresolution.screen.info.link.wiki": "Wiki", + "superresolution.screen.info.name": "情報", "superresolution.screen.info.performance_info.frame_time": "フレーム時間 %1$sms", "superresolution.screen.info.performance_info.upscale_time": "アップスケールアルゴリズム所要時間 %1$sms", "superresolution.screen.info.performance_info.world_time": "ワールド描画所要時間 %1$sms", "superresolution.screen.info.text.algo_support_status": "各アルゴリズムの対応状況", - "superresolution.screen.info.text.author": "作者", - "superresolution.screen.info.text.contributors": "貢献者 / 謝辞", + "superresolution.screen.info.text.author": "作者", + "superresolution.screen.info.text.contributors": "貢献者 / 謝辞", "superresolution.screen.info.text.contributors_order_random": "並び順はランダム", "superresolution.screen.info.text.is_available": "現在サポートされていますか?%s", "superresolution.screen.info.text.min_opengl_version": "最低 OpenGL バージョン: %s.%s", @@ -291,6 +291,7 @@ "superresolution.screen.warn": "警告", "superresolution.screen.config.options.tooltip.algo.experimental_warning": "このアルゴリズムは実験的機能であり、まだ安定していません。\nクラッシュや不具合が発生する可能性があります", "superresolution.screen.config.options.tooltip.algo.experimental_disabled_hint": "このアルゴリズムは実験的機能であり、まだ安定していません。\nクラッシュや不具合が発生する可能性があります。\n使用するには「実験的」→「実験的機能を有効化」をオンにしてください", + "superresolution.screen.config.options.tooltip.algo.disabled_by_shaderpack": "このアルゴリズムはシェーダーパックによって無効化されています", "superresolution.screen.config.options.tooltip.algo.unsupported_reason_header": "このアルゴリズムはサポートされていません。理由:", "superresolution.screen.config.options.tooltip.algo.reason.opengl_version": "· OpenGL バージョンがサポートされていません", "superresolution.screen.config.options.tooltip.algo.reason.opengl_extension": "· 必要な OpenGL 拡張が不足しています", @@ -303,11 +304,13 @@ "superresolution.screen.config.options.tooltip.algo.reason.dev_env_only": "· 開発環境でのみ利用可能です", "superresolution.screen.config.options.tooltip.algo.reason.other": "· その他の理由", "superresolution.screen.config.options.tooltip.upscale_ratio.custom_unsupported": "このアルゴリズムではカスタム倍率はサポートされていません", - "superresolution.screen.config.hint.performance_warning.title": "パフォーマンスと互換性に関する警告", - "superresolution.screen.config.hint.performance_warning.text": "現在シェーダーが有効になっていません。バニラのMinecraftはグラフィック負荷が低いため、超解像によるパフォーマンス向上は見込めず、フレームレートが低下する可能性があります。バニラモードでの互換性は限定的で、一部のMODと描画競合が発生する可能性があります。", + "superresolution.screen.config.hint.performance_warning.title": "パフォーマンスと互換性に関する警告", + "superresolution.screen.config.hint.performance_warning.text": "現在シェーダーが有効になっていません。バニラのMinecraftはグラフィック負荷が低いため、超解像によるパフォーマンス向上は見込めず、フレームレートが低下する可能性があります。バニラモードでの互換性は限定的で、一部のMODと描画競合が発生する可能性があります。", "superresolution.screen.config.hint.b3d_vulkan_unavailable.title": "Super Resolution は Vulkan バックエンドでは動作できません", "superresolution.screen.config.hint.b3d_vulkan_unavailable.text": "現在 Vulkan グラフィックスバックエンドが使用されています。Iris はまだ Vulkan をサポートしていないため、この環境では Super Resolution のアップスケーリング/スケーリング機能を正常に有効化できません。設定画面は開けますが、すべての機能は利用できません。", "superresolution.screen.config.hint.shader_compat_warning.title": "シェーダー互換性警告", "superresolution.screen.config.hint.shader_compat_warning.text": "現在のシェーダーパックはSuper Resolution MODに対応していないため、互換モードで動作します。このモードでは、画面のぼやけ、ゴーストの発生、パフォーマンス低下、他のMODとの互換性低下などの問題が発生する可能性があります。", +"superresolution.screen.config.hint.frame_generation_only_warning.title": "フレーム生成のみモード", +"superresolution.screen.config.hint.frame_generation_only_warning.text": "このシェーダーパックはフレーム生成のみモードを使用しています。超解像度機能は無効です", "superresolution.translate.PoweredByDeepSeek": "?" } diff --git a/common/src/main/resources/assets/super_resolution/lang/zh_cn.json b/common/src/main/resources/assets/super_resolution/lang/zh_cn.json index db98bffa..43e377be 100644 --- a/common/src/main/resources/assets/super_resolution/lang/zh_cn.json +++ b/common/src/main/resources/assets/super_resolution/lang/zh_cn.json @@ -291,6 +291,7 @@ "superresolution.screen.warn": "警告", "superresolution.screen.config.options.tooltip.algo.experimental_warning": "该算法为实验性功能,尚不稳定,可能会导致崩溃或错误", "superresolution.screen.config.options.tooltip.algo.experimental_disabled_hint": "该算法为实验性功能,尚不稳定,可能会导致崩溃或错误\n如需使用请打开 实验性 > 启用实验性功能 选项", + "superresolution.screen.config.options.tooltip.algo.disabled_by_shaderpack": "此算法已被光影包禁用", "superresolution.screen.config.options.tooltip.algo.unsupported_reason_header": "不支持此算法,原因:", "superresolution.screen.config.options.tooltip.algo.reason.opengl_version": "· 当前OpenGL版本不受支持", "superresolution.screen.config.options.tooltip.algo.reason.opengl_extension": "· 缺失必要的OpenGL扩展", @@ -309,5 +310,7 @@ "superresolution.screen.config.hint.b3d_vulkan_unavailable.text": "检测到当前正在使用 Vulkan 图形后端。由于 Iris 暂不支持 Vulkan,Super Resolution 无法在该环境下正常启用升采样/缩放功能;你仍可打开配置界面,但所有功能将不可用。", "superresolution.screen.config.hint.shader_compat_warning.title": "光影兼容性警告", "superresolution.screen.config.hint.shader_compat_warning.text": "当前光影尚未适配超分辨率模组,将以兼容模式运行。此模式下可能出现:画面模糊、重影鬼影、性能下降、与其他模组的兼容性降低等问题", + "superresolution.screen.config.hint.frame_generation_only_warning.title": "仅启用帧生成模式", + "superresolution.screen.config.hint.frame_generation_only_warning.text": "此光影使用仅帧生成模式,超分辨率功能已禁用", "superresolution.translate.PoweredByDeepSeek": "?" } diff --git a/common/src/main/resources/assets/super_resolution/lang/zh_tw.json b/common/src/main/resources/assets/super_resolution/lang/zh_tw.json index fbc53763..453e80d6 100644 --- a/common/src/main/resources/assets/super_resolution/lang/zh_tw.json +++ b/common/src/main/resources/assets/super_resolution/lang/zh_tw.json @@ -290,6 +290,7 @@ "superresolution.screen.warn": "警告", "superresolution.screen.config.options.tooltip.algo.experimental_warning": "此演算法為實驗性功能,尚不穩定,可能會導致崩潰或錯誤", "superresolution.screen.config.options.tooltip.algo.experimental_disabled_hint": "此演算法為實驗性功能,尚不穩定,可能會導致崩潰或錯誤\n如需使用請開啟 實驗性 > 啟用實驗性功能 選項", + "superresolution.screen.config.options.tooltip.algo.disabled_by_shaderpack": "此演算法已被光影包停用", "superresolution.screen.config.options.tooltip.algo.unsupported_reason_header": "不支援此演算法,原因:", "superresolution.screen.config.options.tooltip.algo.reason.opengl_version": "· 目前 OpenGL 版本不受支援", "superresolution.screen.config.options.tooltip.algo.reason.opengl_extension": "· 缺失必要的 OpenGL 擴充功能", @@ -308,5 +309,7 @@ "superresolution.screen.config.hint.b3d_vulkan_unavailable.text": "偵測到目前正在使用 Vulkan 圖形後端。由於 Iris 暫不支援 Vulkan,Super Resolution 無法在此環境下正常啟用升頻/縮放功能;你仍可開啟設定介面,但所有功能將無法使用。", "superresolution.screen.config.hint.shader_compat_warning.title": "光影相容性警告", "superresolution.screen.config.hint.shader_compat_warning.text": "目前光影尚未適配超解析度模組,將以相容模式運行。此模式下可能出現:畫面模糊、重影鬼影、效能下降、與其他模組的相容性降低等問題", +"superresolution.screen.config.hint.frame_generation_only_warning.title": "僅啟用幀生成模式", +"superresolution.screen.config.hint.frame_generation_only_warning.text": "此光影使用僅幀生成模式,超解析度功能已停用", "superresolution.translate.PoweredByDeepSeek": "?" } diff --git a/common/src/shadercompat/java/io/homo/superresolution/common/minecraft/handler/shadercompat/SRCompatBuiltinMacros.java b/common/src/shadercompat/java/io/homo/superresolution/common/minecraft/handler/shadercompat/SRCompatBuiltinMacros.java index 3553dd6c..c428d221 100644 --- a/common/src/shadercompat/java/io/homo/superresolution/common/minecraft/handler/shadercompat/SRCompatBuiltinMacros.java +++ b/common/src/shadercompat/java/io/homo/superresolution/common/minecraft/handler/shadercompat/SRCompatBuiltinMacros.java @@ -27,6 +27,8 @@ import io.homo.superresolution.common.upscale.AlgorithmDescriptions; import io.homo.superresolution.common.upscale.AlgorithmManager; +import io.homo.superresolution.common.minecraft.handler.shadercompat.ShaderCompatHandler; + import java.util.*; public class SRCompatBuiltinMacros { @@ -54,6 +56,14 @@ public static void addMacros(JsonMacroPreprocessor preprocessor) { AlgorithmDescription selectedAlgorithm = description != null ? description : SuperResolutionConfig.getUpscaleAlgorithm(); + boolean frameGenOnly = false; + SRShaderCompatData data = ShaderCompatHandler.getShaderCompatData(); + if (data != null) { + SRShaderCompatData.WorldProfile profile = data.getProfileForWorld("*"); + if (profile != null && profile.upscale != null) { + frameGenOnly = profile.upscale.onlySupportsFrameGeneration; + } + } preprocessor.addMacro("SR_ENABLE", "1"); preprocessor.addMacro("SR_DISABLE", "0"); preprocessor.addMacro("SR_ALGO_SUPPORTS_JITTER", @@ -70,9 +80,9 @@ public static void addMacros(JsonMacroPreprocessor preprocessor) { preprocessor.addMacro("SR_SCREEN_HEIGHT", Integer.toString(SuperResolutionAPI.getScreenHeight())); preprocessor.addMacro("SR_UPSCALE_RATIO", - Float.toString(SuperResolutionConfig.getUpscaleRatio())); + Float.toString(frameGenOnly ? 1.0f : SuperResolutionConfig.getUpscaleRatio())); preprocessor.addMacro("SR_RENDER_SCALE_FACTOR", - Float.toString(SuperResolutionConfig.getRenderScaleFactor())); + Float.toString(frameGenOnly ? 1.0f : SuperResolutionConfig.getRenderScaleFactor())); preprocessor.addMacro("SR_JITTER_SEQUENCE_LENGTH", Integer.toString(AlgorithmManager.getConfiguredJitterSequenceLength())); preprocessor.addMacro("SR_ALGO_DLSS_RENDERPRESET", @@ -101,17 +111,29 @@ public static void addMacros(JsonMacroPreprocessor preprocessor) { // endregion // region V2 - preprocessor.addMacro("SR_CONFIG_SCHEMA_VERSION", "2"); - if (SuperResolutionConfig.isEnableUpscaleOriginal()) { + boolean frameGenOnlyV2 = false; + SRShaderCompatData dataV2 = ShaderCompatHandler.getShaderCompatData(); + if (dataV2 != null) { + SRShaderCompatData.WorldProfile profileV2 = dataV2.getProfileForWorld("*"); + if (profileV2 != null && profileV2.upscale != null) { + frameGenOnlyV2 = profileV2.upscale.onlySupportsFrameGeneration; + } + } + float rsf = frameGenOnlyV2 ? 1.0f : SuperResolutionConfig.getRenderScaleFactor(); + float ratio = frameGenOnlyV2 ? 1.0f : SuperResolutionConfig.getUpscaleRatio(); preprocessor.addMacro("SR_UPSCALE_RATIO_HALF", - Float.toString(SuperResolutionConfig.getUpscaleRatio() * 0.5F)); + Float.toString(ratio * 0.5F)); preprocessor.addMacro("SR_RENDER_SCALE_FACTOR_HALF", - Float.toString(SuperResolutionConfig.getRenderScaleFactor() * 0.5F)); + Float.toString(rsf * 0.5F)); } else { preprocessor.addMacro("SR_UPSCALE_RATIO_HALF", Float.toString(0.5F)); preprocessor.addMacro("SR_RENDER_SCALE_FACTOR_HALF", Float.toString(0.5F)); } // endregion + + // region V3 + preprocessor.addMacro("SR_CONFIG_SCHEMA_VERSION", Integer.toString(SRCompatConfigParser.LATEST_CONFIG_VERSION)); + // endregion } } diff --git a/common/src/shadercompat/java/io/homo/superresolution/common/minecraft/handler/shadercompat/SRCompatConfigParser.java b/common/src/shadercompat/java/io/homo/superresolution/common/minecraft/handler/shadercompat/SRCompatConfigParser.java index 618b8f6d..0cf8e492 100644 --- a/common/src/shadercompat/java/io/homo/superresolution/common/minecraft/handler/shadercompat/SRCompatConfigParser.java +++ b/common/src/shadercompat/java/io/homo/superresolution/common/minecraft/handler/shadercompat/SRCompatConfigParser.java @@ -26,6 +26,8 @@ import io.homo.superresolution.common.minecraft.handler.shadercompat.v1.SRCompatV1Processor; import io.homo.superresolution.common.minecraft.handler.shadercompat.v2.SRCompatConfigV2Parser; import io.homo.superresolution.common.minecraft.handler.shadercompat.v2.SRCompatV2Processor; +import io.homo.superresolution.common.minecraft.handler.shadercompat.v3.SRCompatConfigV3Parser; +import io.homo.superresolution.common.minecraft.handler.shadercompat.v3.SRCompatV3Processor; import java.nio.file.Files; import java.nio.file.Path; @@ -34,7 +36,7 @@ public class SRCompatConfigParser { private static final Gson GSON = new GsonBuilder().create(); - public static final int LATEST_CONFIG_VERSION = 2; + public static final int LATEST_CONFIG_VERSION = 3; private static final Pattern SCHEMA_VERSION_PATTERN = Pattern.compile("\"schema_version\"\\s*:\\s*(\\d+)"); public static SRShaderCompatData load(Path file) { @@ -63,6 +65,8 @@ public static SRShaderCompatData load(Path file, JsonMacroPreprocessor preproces return SRCompatConfigV1Parser.parse(rootObj); } else if (version == 2) { return SRCompatConfigV2Parser.parse(rootObj); + } else if (version == 3) { + return SRCompatConfigV3Parser.parse(rootObj); } else { SuperResolution.LOGGER.error("不支持的光影接口配置版本: " + version); return null; @@ -107,6 +111,7 @@ public static int readVersion(Path file) { public static SRCompatProcessor createProcessor(int version) { if (version == 1) return new SRCompatV1Processor(); if (version == 2) return new SRCompatV2Processor(); + if (version == 3) return new SRCompatV3Processor(); SuperResolution.LOGGER.error("不支持的光影接口配置版本: " + version); return null; } diff --git a/common/src/shadercompat/java/io/homo/superresolution/common/minecraft/handler/shadercompat/SRShaderCompatData.java b/common/src/shadercompat/java/io/homo/superresolution/common/minecraft/handler/shadercompat/SRShaderCompatData.java index a905afdd..49001e30 100644 --- a/common/src/shadercompat/java/io/homo/superresolution/common/minecraft/handler/shadercompat/SRShaderCompatData.java +++ b/common/src/shadercompat/java/io/homo/superresolution/common/minecraft/handler/shadercompat/SRShaderCompatData.java @@ -76,6 +76,8 @@ public static class UpscaleConfig { public final boolean isAutoExposure; public final boolean isMotionJittered; public final @Nullable CustomsConfig customs; + public final boolean onlySupportsFrameGeneration; + public final List disabledAlgorithms; public UpscaleConfig(boolean enabled, PipelineTrigger trigger, TextureFormat internalFormat, @@ -91,6 +93,27 @@ public UpscaleConfig(boolean enabled, PipelineTrigger trigger, TextureFormat int @Nullable SourceConfig preExposure, boolean isHdrInput,boolean isAutoExposure,boolean isMotionJittered, @Nullable CustomsConfig customs) { + this(enabled, trigger, internalFormat, inputTextures, outputTextures, + preExposure, isHdrInput, isAutoExposure, isMotionJittered, customs, false); + } + + public UpscaleConfig(boolean enabled, PipelineTrigger trigger, TextureFormat internalFormat, + Map inputTextures, Map outputTextures, + @Nullable SourceConfig preExposure, + boolean isHdrInput,boolean isAutoExposure,boolean isMotionJittered, + @Nullable CustomsConfig customs, + boolean onlySupportsFrameGeneration) { + this(enabled, trigger, internalFormat, inputTextures, outputTextures, + preExposure, isHdrInput, isAutoExposure, isMotionJittered, customs, onlySupportsFrameGeneration, Collections.emptyList()); + } + + public UpscaleConfig(boolean enabled, PipelineTrigger trigger, TextureFormat internalFormat, + Map inputTextures, Map outputTextures, + @Nullable SourceConfig preExposure, + boolean isHdrInput,boolean isAutoExposure,boolean isMotionJittered, + @Nullable CustomsConfig customs, + boolean onlySupportsFrameGeneration, + List disabledAlgorithms) { this.enabled = enabled; this.trigger = trigger; this.internalFormat = internalFormat; @@ -101,6 +124,8 @@ public UpscaleConfig(boolean enabled, PipelineTrigger trigger, TextureFormat int this.isAutoExposure = isAutoExposure; this.isMotionJittered = isMotionJittered; this.customs = customs; + this.onlySupportsFrameGeneration = onlySupportsFrameGeneration; + this.disabledAlgorithms = disabledAlgorithms != null ? disabledAlgorithms : Collections.emptyList(); } } diff --git a/common/src/shadercompat/java/io/homo/superresolution/common/minecraft/handler/shadercompat/ShaderCompatHandler.java b/common/src/shadercompat/java/io/homo/superresolution/common/minecraft/handler/shadercompat/ShaderCompatHandler.java index f3e0298c..2f82c62b 100644 --- a/common/src/shadercompat/java/io/homo/superresolution/common/minecraft/handler/shadercompat/ShaderCompatHandler.java +++ b/common/src/shadercompat/java/io/homo/superresolution/common/minecraft/handler/shadercompat/ShaderCompatHandler.java @@ -27,6 +27,7 @@ import io.homo.superresolution.common.minecraft.handler.IMinecraftRenderHandler; import io.homo.superresolution.common.minecraft.handler.RenderHandlerManager; import io.homo.superresolution.common.minecraft.handler.shadercompat.v2.SRCompatV2Processor; +import io.homo.superresolution.common.minecraft.handler.shadercompat.v3.SRCompatV3Processor; import io.homo.superresolution.common.mixin.core.accessor.PostChainAccessor; import io.homo.superresolution.common.upscale.InteropResourcesConverter; import io.homo.superresolution.core.graphics.impl.framebuffer.IBindableFrameBuffer; @@ -430,6 +431,7 @@ public void destroy() { renderTargets.clear(); InteropResourcesConverter.destroy(); SRCompatV2Processor.destroyPipelineCache(); + SRCompatV3Processor.destroyPipelineCache(); } @Override diff --git a/common/src/shadercompat/java/io/homo/superresolution/common/minecraft/handler/shadercompat/v3/SRCompatConfigV3Parser.java b/common/src/shadercompat/java/io/homo/superresolution/common/minecraft/handler/shadercompat/v3/SRCompatConfigV3Parser.java new file mode 100644 index 00000000..dbb21394 --- /dev/null +++ b/common/src/shadercompat/java/io/homo/superresolution/common/minecraft/handler/shadercompat/v3/SRCompatConfigV3Parser.java @@ -0,0 +1,513 @@ +/* + * Super Resolution + * Copyright (c) 2026. 187J3X1-114514 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package io.homo.superresolution.common.minecraft.handler.shadercompat.v3; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonObject; +import io.homo.superresolution.api.registry.AlgorithmRegistry; +import io.homo.superresolution.common.SuperResolution; +import io.homo.superresolution.common.minecraft.handler.shadercompat.SRShaderCompatData; +import io.homo.superresolution.common.minecraft.handler.shadercompat.TextureRegion; +import io.homo.superresolution.core.graphics.impl.texture.TextureFormat; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class SRCompatConfigV3Parser { + private static final Gson GSON = new GsonBuilder().create(); + + public static SRShaderCompatData parse(JsonObject root) { + RawSchemaV3 dto = GSON.fromJson(root, RawSchemaV3.class); + + Map profiles = new HashMap<>(); + SRShaderCompatData.WorldProfile defaultProfile = null; + + if (dto.profiles != null) { + for (Map.Entry entry : dto.profiles.entrySet()) { + String worldKey = entry.getKey(); + RawSchemaV3.RawProfile rawProfile = entry.getValue(); + if (rawProfile == null) { + SuperResolution.LOGGER.error("配置错误:profile '{}' 为 null", worldKey); + return null; + } + + // --- 验证 upscale 部分 --- + SRShaderCompatData.PipelineTrigger trigger = null; + if (rawProfile.upscale != null && rawProfile.upscale.trigger != null) { + RawSchemaV3.RawTrigger rt = rawProfile.upscale.trigger; + if (rt.type == null || (!"before".equalsIgnoreCase(rt.type) && !"after".equalsIgnoreCase(rt.type))) { + SuperResolution.LOGGER.error("配置错误:profile '{}' 中 upscale.trigger.type 必须为 'before' 或 'after',但得到: {}", worldKey, rt.type); + return null; + } + if (rt.pass == null || rt.pass.isBlank()) { + SuperResolution.LOGGER.error("配置错误:profile '{}' 中 upscale.trigger.pass 不能为空。", worldKey); + return null; + } + + SRShaderCompatData.PipelineTrigger.Order order = + "before".equalsIgnoreCase(rt.type) ? + SRShaderCompatData.PipelineTrigger.Order.BEFORE : + SRShaderCompatData.PipelineTrigger.Order.AFTER; + + trigger = new SRShaderCompatData.PipelineTrigger(order, rt.pass); + } + + SRShaderCompatData.UpscaleConfig upscaleConfig; + if (rawProfile.upscale != null) { + String internalFormat = rawProfile.upscale.internal_format; + if (internalFormat != null && parseTextureFormat(internalFormat) == null) { + SuperResolution.LOGGER.error("配置错误:profile '{}' 中 upscale.internal_format 非法: {}", worldKey, internalFormat); + return null; + } + + if (rawProfile.upscale.inputs != null) { + for (Map.Entry inEntry : rawProfile.upscale.inputs.entrySet()) { + String inKey = inEntry.getKey(); + RawSchemaV3.RawInputTexture rit = inEntry.getValue(); + if (rit == null) { + SuperResolution.LOGGER.error("配置错误:profile '{}' upscale.inputs.{} 为 null", worldKey, inKey); + return null; + } + if (rit.enabled && (rit.src == null || rit.src.isBlank())) { + SuperResolution.LOGGER.error("配置错误:profile '{}' upscale.inputs.{} 启用但未指定 src。", worldKey, inKey); + return null; + } + if (!isValidRegionList(rit.region)) { + SuperResolution.LOGGER.error("配置错误:profile '{}' upscale.inputs.{} 的 region 必须为长度为 4 的整数数组。", worldKey, inKey); + return null; + } + } + } + + if (rawProfile.upscale.outputs != null) { + for (Map.Entry outEntry : rawProfile.upscale.outputs.entrySet()) { + String outKey = outEntry.getKey(); + RawSchemaV3.RawOutputTexture rot = outEntry.getValue(); + if (rot == null) { + SuperResolution.LOGGER.error("配置错误:profile '{}' upscale.outputs.{} 为 null", worldKey, outKey); + return null; + } + if (rot.enabled && (rot.target == null || rot.target.isEmpty())) { + SuperResolution.LOGGER.error("配置错误:profile '{}' upscale.outputs.{} 启用但未指定 target。", worldKey, outKey); + return null; + } + if (!isValidRegionList(rot.region)) { + SuperResolution.LOGGER.error("配置错误:profile '{}' upscale.outputs.{} 的 region 必须为长度为 4 的整数数组。", worldKey, outKey); + return null; + } + } + } + + SRShaderCompatData.SourceConfig preExposureConfig = null; + if (rawProfile.upscale.pre_exposure != null) { + if (!validateRawSourceConfig(rawProfile.upscale.pre_exposure, worldKey + " upscale.pre_exposure")) return null; + SRShaderCompatData.SourceConfig.ValueType vType; + try { + vType = SRShaderCompatData.SourceConfig.ValueType.fromString(rawProfile.upscale.pre_exposure.type); + } catch (IllegalArgumentException ex) { + SuperResolution.LOGGER.error("配置错误:profile '{}' upscale.pre_exposure.type 非法: {}", worldKey, ex.getMessage()); + return null; + } + if (vType != SRShaderCompatData.SourceConfig.ValueType.FLOAT && + vType != SRShaderCompatData.SourceConfig.ValueType.INT && + vType != SRShaderCompatData.SourceConfig.ValueType.UINT) { + SuperResolution.LOGGER.error("配置错误:profile '{}' upscale.pre_exposure.type 必须为标量类型 (float/int/uint),但得到: {}", worldKey, rawProfile.upscale.pre_exposure.type); + return null; + } + try { + preExposureConfig = new SRShaderCompatData.SourceConfig( + rawProfile.upscale.pre_exposure.source, + rawProfile.upscale.pre_exposure.type, + rawProfile.upscale.pre_exposure.value + ); + } catch (IllegalArgumentException ex) { + SuperResolution.LOGGER.error("配置错误:profile '{}' upscale.pre_exposure 中存在无效值: {}", worldKey, ex.getMessage()); + return null; + } + } + boolean autoExposureEffective = !(rawProfile.upscale != null && + rawProfile.upscale.inputs != null && + rawProfile.upscale.inputs.containsKey("exposure")); + if ( + rawProfile.upscale != null && + rawProfile.upscale.inputs != null && + rawProfile.upscale.inputs.containsKey("exposure") && + rawProfile.upscale.auto_exposure + ){ + SuperResolution.LOGGER.warn("配置警告:profile '{}' 中 upscale.auto_exposure 为 true ,但同时启用 exposure 输入纹理,已自动忽略auto_exposure设置,默认为false。", worldKey); + } + SRShaderCompatData.CustomsConfig customsConfig = rawProfile.upscale.customs != null + ? new SRShaderCompatData.CustomsConfig(rawProfile.upscale.customs.motion_vector_preprocessing_function) + : null; + + List disabledAlgorithms = java.util.Collections.emptyList(); + if (rawProfile.upscale.disabled_algorithms != null) { + for (String algoId : rawProfile.upscale.disabled_algorithms) { + if (algoId == null || algoId.isBlank()) { + SuperResolution.LOGGER.error("配置错误:profile '{}' 中 upscale.disabled_algorithms 包含空值。", worldKey); + return null; + } + if (!AlgorithmRegistry.getAlgorithmMap().containsKey(algoId)) { + SuperResolution.LOGGER.error("配置错误:profile '{}' 中 upscale.disabled_algorithms 包含未知的算法 ID: {}", worldKey, algoId); + return null; + } + } + disabledAlgorithms = rawProfile.upscale.disabled_algorithms; + } + + upscaleConfig = new SRShaderCompatData.UpscaleConfig( + rawProfile.upscale.enabled, + trigger, + parseTextureFormat(rawProfile.upscale.internal_format), + mapInputTextures(rawProfile.upscale.inputs, worldKey), + mapOutputTextures(rawProfile.upscale.outputs, worldKey), + preExposureConfig, + rawProfile.upscale.hdr, + rawProfile.upscale.auto_exposure && autoExposureEffective, + rawProfile.upscale.motion_jittered, + customsConfig, + rawProfile.upscale.only_supports_frame_generation, + disabledAlgorithms + ); + } else { + upscaleConfig = new SRShaderCompatData.UpscaleConfig( + false, + null, + TextureFormat.R11G11B10F, + new HashMap<>(), + new HashMap<>(), + null, + false, + true, + false, + null + ); + } + + // --- 验证 jitter 部分 --- + SRShaderCompatData.JitterConfig jitterConfig; + if (rawProfile.jitter != null) { + RawSchemaV3.RawJitter rj = rawProfile.jitter; + SRShaderCompatData.JitterConfig.JitterSource jSource = SRShaderCompatData.JitterConfig.JitterSource.MOD; + if (rj.source != null) { + if ("shaderpack".equalsIgnoreCase(rj.source)) { + jSource = SRShaderCompatData.JitterConfig.JitterSource.SHADERPACK; + } else if ("mod".equalsIgnoreCase(rj.source)) { + jSource = SRShaderCompatData.JitterConfig.JitterSource.MOD; + } else { + SuperResolution.LOGGER.error("配置错误:profile '{}' jitter.source 必须为 'mod' 或 'shaderpack',但得到: {}", worldKey, rj.source); + return null; + } + } + + SRShaderCompatData.JitterSourceConfig sc = null; + if (rj.source_config != null) { + RawSchemaV3.RawJitterSourceConfig rc = rj.source_config; + if (rc.jitter_offset == null) { + SuperResolution.LOGGER.error("配置错误:profile '{}' jitter.source_config.jitter_offset 不能为空。", worldKey); + return null; + } + if (rc.jitter_sequence_length == null) { + SuperResolution.LOGGER.error("配置错误:profile '{}' jitter.source_config.jitter_sequence_length 不能为空。", worldKey); + return null; + } + + if (!validateRawSourceConfig(rc.jitter_offset, worldKey + " jitter.source_config.jitter_offset")) return null; + if (!validateRawSourceConfig(rc.jitter_sequence_length, worldKey + " jitter.source_config.jitter_sequence_length")) return null; + + SRShaderCompatData.SourceConfig offsetSC; + SRShaderCompatData.SourceConfig seqLenSC; + try { + offsetSC = new SRShaderCompatData.SourceConfig( + rc.jitter_offset.source, + rc.jitter_offset.type, + rc.jitter_offset.value + ); + seqLenSC = new SRShaderCompatData.SourceConfig( + rc.jitter_sequence_length.source, + rc.jitter_sequence_length.type, + rc.jitter_sequence_length.value + ); + } catch (IllegalArgumentException ex) { + SuperResolution.LOGGER.error("配置错误:profile '{}' 的 jitter.source_config 中存在无效的 source/type 值: {}", worldKey, ex.getMessage()); + return null; + } + + sc = new SRShaderCompatData.JitterSourceConfig(offsetSC, seqLenSC); + } + + jitterConfig = new SRShaderCompatData.JitterConfig(rj.enabled, jSource, sc); + } else { + jitterConfig = new SRShaderCompatData.JitterConfig(false); + } + + SRShaderCompatData.WorldProfile profile = new SRShaderCompatData.WorldProfile( + true, + upscaleConfig, + jitterConfig + ); + + profiles.put(worldKey, profile); + if ("*".equals(worldKey)) { + defaultProfile = profile; + } + } + } + + return new SRShaderCompatData(3, profiles, defaultProfile, new SRCompatV3Processor()); + } + + private static TextureFormat parseTextureFormat(String formatStr) { + if (formatStr == null) return null; + return switch (formatStr.toLowerCase()) { + case "rgba8" -> TextureFormat.RGBA8; + case "rgba16f" -> TextureFormat.RGBA16F; + case "r11g11b10f" -> TextureFormat.R11G11B10F; + default -> null; + }; + } + + private static Map mapInputTextures(Map source, String worldKey) { + Map result = new HashMap<>(); + if (source == null) return result; + for (Map.Entry e : source.entrySet()) { + String k = e.getKey(); + RawSchemaV3.RawInputTexture v = e.getValue(); + if (v == null) { + SuperResolution.LOGGER.error("配置错误:profile '{}' upscale.inputs.{} 为 null", worldKey, k); + return new HashMap<>(); + } + if (v.enabled && (v.src == null || v.src.isBlank())) { + SuperResolution.LOGGER.error("配置错误:profile '{}' upscale.inputs.{} 启用但未指定 src。", worldKey, k); + return new HashMap<>(); + } + if (!isValidRegionList(v.region)) { + SuperResolution.LOGGER.error("配置错误:profile '{}' upscale.inputs.{} 的 region 必须为长度为 4 的整数数组。", worldKey, k); + return new HashMap<>(); + } + result.put(k, new SRShaderCompatData.InputTexture( + v.enabled, + v.src, + TextureRegion.fromList(v.region) + )); + } + return result; + } + + private static Map mapOutputTextures(Map source, String worldKey) { + Map result = new HashMap<>(); + if (source == null) return result; + for (Map.Entry e : source.entrySet()) { + String k = e.getKey(); + RawSchemaV3.RawOutputTexture v = e.getValue(); + if (v == null) { + SuperResolution.LOGGER.error("配置错误:profile '{}' upscale.outputs.{} 为 null", worldKey, k); + return new HashMap<>(); + } + if (v.enabled && (v.target == null || v.target.isEmpty())) { + SuperResolution.LOGGER.error("配置错误:profile '{}' upscale.outputs.{} 启用但未指定 target。", worldKey, k); + return new HashMap<>(); + } + if (!isValidRegionList(v.region)) { + SuperResolution.LOGGER.error("配置错误:profile '{}' upscale.outputs.{} 的 region 必须为长度为 4 的整数数组。", worldKey, k); + return new HashMap<>(); + } + result.put(k, new SRShaderCompatData.OutputTexture( + v.enabled, + v.target, + TextureRegion.fromList(v.region) + )); + } + return result; + } + + private static boolean isValidRegionList(List region) { + if (region == null) return false; + if (region.size() != 4) return false; + return true; + } + + private static boolean validateRawSourceConfig(RawSchemaV3.RawSourceConfig rsc, String context) { + if (rsc == null) { + SuperResolution.LOGGER.error("配置错误:{} 为 null", context); + return false; + } + if (rsc.source == null || rsc.source.isBlank()) { + SuperResolution.LOGGER.error("配置错误:{}.source 不能为空", context); + return false; + } + if (rsc.type == null || rsc.type.isBlank()) { + SuperResolution.LOGGER.error("配置错误:{}.type 不能为空", context); + return false; + } + try { + SRShaderCompatData.SourceConfig.SourceType.fromString(rsc.source); + SRShaderCompatData.SourceConfig.ValueType.fromString(rsc.type); + } catch (IllegalArgumentException ex) { + SuperResolution.LOGGER.error("配置错误:{} 中 source/type 非法: {}", context, ex.getMessage()); + return false; + } + + SRShaderCompatData.SourceConfig.SourceType sType = SRShaderCompatData.SourceConfig.SourceType.fromString(rsc.source); + SRShaderCompatData.SourceConfig.ValueType vType = SRShaderCompatData.SourceConfig.ValueType.fromString(rsc.type); + + if (sType == SRShaderCompatData.SourceConfig.SourceType.CONST) { + if (rsc.value == null) { + SuperResolution.LOGGER.error("配置错误:{} 为 CONST 时 value 不能为空", context); + return false; + } + switch (vType) { + case FLOAT, INT, UINT -> { + if (!(rsc.value instanceof Number)) { + SuperResolution.LOGGER.error("配置错误:{} 为 CONST 且 type 为 {} 时,value 必须是数字", context, vType); + return false; + } + } + case VECTOR2F -> { + if (!(rsc.value instanceof List)) { + SuperResolution.LOGGER.error("配置错误:{} 为 CONST 且 type 为 VECTOR2F 时,value 必须为长度为 2 的数值数组", context); + return false; + } + List list = (List) rsc.value; + if (list.size() != 2) { + SuperResolution.LOGGER.error("配置错误:{} 为 CONST 且 type 为 VECTOR2F 时,value 长度应为 2,实际: {}", context, list.size()); + return false; + } + if (!allElementsAreNumbers(list)) { + SuperResolution.LOGGER.error("配置错误:{} 为 CONST 且 type 为 VECTOR2F 时,value 中的元素必须为数字", context); + return false; + } + } + case VECTOR3F -> { + if (!(rsc.value instanceof List)) { + SuperResolution.LOGGER.error("配置错误:{} 为 CONST 且 type 为 VECTOR3F 时,value 必须为长度为 3 的数值数组", context); + return false; + } + List list = (List) rsc.value; + if (list.size() != 3) { + SuperResolution.LOGGER.error("配置错误:{} 为 CONST 且 type 为 VECTOR3F 时,value 长度应为 3,实际: {}", context, list.size()); + return false; + } + if (!allElementsAreNumbers(list)) { + SuperResolution.LOGGER.error("配置错误:{} 为 CONST 且 type 为 VECTOR3F 时,value 中的元素必须为数字", context); + return false; + } + } + case VECTOR4F -> { + if (!(rsc.value instanceof List)) { + SuperResolution.LOGGER.error("配置错误:{} 为 CONST 且 type 为 VECTOR4F 时,value 必须为长度为 4 的数值数组", context); + return false; + } + List list = (List) rsc.value; + if (list.size() != 4) { + SuperResolution.LOGGER.error("配置错误:{} 为 CONST 且 type 为 VECTOR4F 时,value 长度应为 4,实际: {}", context, list.size()); + return false; + } + if (!allElementsAreNumbers(list)) { + SuperResolution.LOGGER.error("配置错误:{} 为 CONST 且 type 为 VECTOR4F 时,value 中的元素必须为数字", context); + return false; + } + } + } + } else { + if (!(rsc.value instanceof String)) { + SuperResolution.LOGGER.error("配置错误:{} 为 {} 时,value 必须为字符串,表示变量或 uniform 名称", context, rsc.source); + return false; + } + if (((String) rsc.value).isBlank()) { + SuperResolution.LOGGER.error("配置错误:{} 的 value 不能为空字符串", context); + return false; + } + } + + return true; + } + + private static boolean allElementsAreNumbers(List list) { + for (Object o : list) { + if (!(o instanceof Number)) return false; + } + return true; + } + + private static class RawSchemaV3 { + int schema_version; + Map profiles; + + static class RawProfile { + RawUpscale upscale; + RawJitter jitter; + } + + static class RawUpscale { + boolean enabled; + RawTrigger trigger; + String internal_format; + Map inputs; + Map outputs; + RawSourceConfig pre_exposure; + boolean hdr; + boolean auto_exposure; + boolean motion_jittered; + RawCustoms customs; + boolean only_supports_frame_generation; + List disabled_algorithms; + } + + static class RawCustoms { + String motion_vector_preprocessing_function; + } + + static class RawTrigger { + String type; + String pass; + } + + static class RawJitter { + boolean enabled; + String source; + RawJitterSourceConfig source_config; + } + + static class RawJitterSourceConfig { + RawSourceConfig jitter_offset; + RawSourceConfig jitter_sequence_length; + } + + static class RawSourceConfig { + String source; + String type; + Object value; + } + + static class RawInputTexture { + boolean enabled; + String src; + List region; + } + + static class RawOutputTexture { + boolean enabled; + List target; + List region; + } + } +} diff --git a/common/src/shadercompat/java/io/homo/superresolution/common/minecraft/handler/shadercompat/v3/SRCompatV3Processor.java b/common/src/shadercompat/java/io/homo/superresolution/common/minecraft/handler/shadercompat/v3/SRCompatV3Processor.java new file mode 100644 index 00000000..dd524ba7 --- /dev/null +++ b/common/src/shadercompat/java/io/homo/superresolution/common/minecraft/handler/shadercompat/v3/SRCompatV3Processor.java @@ -0,0 +1,344 @@ +/* + * Super Resolution + * Copyright (c) 2026. 187J3X1-114514 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package io.homo.superresolution.common.minecraft.handler.shadercompat.v3; + +import io.homo.superresolution.api.AbstractAlgorithm; +import io.homo.superresolution.api.SuperResolutionAPI; +import io.homo.superresolution.api.registry.AlgorithmDescription; +import io.homo.superresolution.api.registry.AlgorithmRegistry; +import io.homo.superresolution.core.RenderSystems; +import io.homo.superresolution.core.graphics.impl.pipeline.ComputePipeline; +import io.homo.superresolution.core.graphics.impl.shader.IShaderProgram; +import io.homo.superresolution.core.graphics.impl.shader.ShaderDescription; +import io.homo.superresolution.core.graphics.impl.shader.ShaderSource; +import io.homo.superresolution.core.graphics.impl.shader.ShaderType; +import io.homo.superresolution.core.utils.FileReadHelper; +import io.homo.superresolution.common.config.SuperResolutionConfig; +import io.homo.superresolution.common.config.enums.DLSSRenderPreset; +import io.homo.superresolution.common.minecraft.handler.RenderHandlerManager; +import io.homo.superresolution.common.minecraft.handler.shadercompat.MacroRegistrar; +import io.homo.superresolution.common.minecraft.handler.shadercompat.ShaderCompatHandler; +import io.homo.superresolution.common.minecraft.handler.shadercompat.SRCompatProcessor; +import io.homo.superresolution.common.minecraft.handler.shadercompat.SRShaderCompatData; +import io.homo.superresolution.common.minecraft.handler.shadercompat.UniformRegistrar; +import io.homo.superresolution.common.upscale.AlgorithmDescriptions; +import io.homo.superresolution.common.upscale.AlgorithmManager; +import io.homo.superresolution.core.graphics.impl.command.ICommandBuffer; +import io.homo.superresolution.core.graphics.impl.texture.ITexture; +import io.homo.superresolution.shadercompat.IrisShaderCompatUpscaleDispatcher; +import io.homo.superresolution.shadercompat.IrisShaderCompatUtils; +import org.joml.Vector2f; +import org.joml.Vector2i; + +import java.util.*; + +public class SRCompatV3Processor implements SRCompatProcessor { + private static final Map mvPreprocessPipelineCache = new HashMap<>(); + + public static void destroyPipelineCache() { + for (ComputePipeline pipeline : mvPreprocessPipelineCache.values()) { + IShaderProgram shader = pipeline.shader(); + pipeline.destroy(); + shader.destroy(); + } + mvPreprocessPipelineCache.clear(); + } + + @Override + public int version() { + return 3; + } + + @Override + public boolean needsPreProcessColor(SRShaderCompatData config, AbstractAlgorithm algorithm, AlgorithmDescription description) { + return false; + } + + @Override + public boolean needsPreProcessDepth(SRShaderCompatData config, AbstractAlgorithm algorithm, AlgorithmDescription description) { + return false; + } + + @Override + public boolean needsPreProcessMotionVectors(SRShaderCompatData config, AbstractAlgorithm algorithm, AlgorithmDescription description) { + if ( + description.equals(AlgorithmDescriptions.FSR) || + description.equals(AlgorithmDescriptions.DLSS) || + description.equals(AlgorithmDescriptions.XESS) + ) { + return false; + }else { + return IrisShaderCompatUtils.getCurrentConfig() + .map(p -> p.upscale.customs != null && p.upscale.customs.motionVectorPreprocessingFunction != null) + .orElse(false); + } + + } + + @Override + public boolean needsPreProcessExposure(SRShaderCompatData config, AbstractAlgorithm algorithm, AlgorithmDescription description) { + return false; + } + + @Override + public boolean needsAdaptJitter(SRShaderCompatData config, AbstractAlgorithm algorithm, AlgorithmDescription description) { + return true; + } + + @Override + public boolean needsAdaptPreExposure(SRShaderCompatData config, AbstractAlgorithm algorithm, AlgorithmDescription description) { + return false; + } + + @Override + public Vector2f adaptJitterForAlgorithm(Vector2f rawJitter, AbstractAlgorithm algorithm, SRShaderCompatData config, AlgorithmDescription description) { + return rawJitter; + } + + @Override + public Vector2f adaptJitterForShaderpack(Vector2f rawJitter, AbstractAlgorithm algorithm, SRShaderCompatData config, AlgorithmDescription description) { + if ( + description.equals(AlgorithmDescriptions.FSR) || + description.equals(AlgorithmDescriptions.DLSS) || + description.equals(AlgorithmDescriptions.XESS) + ) { + return rawJitter.mul(1, -1); + }else { + return rawJitter; + } + } + + @Override + public void preProcessColor(ITexture input, ITexture output, ICommandBuffer commandBuffer, + SRShaderCompatData config, AbstractAlgorithm algorithm, AlgorithmDescription description) { + } + + @Override + public void preProcessDepth(ITexture input, ITexture output, ICommandBuffer commandBuffer, + SRShaderCompatData config, AbstractAlgorithm algorithm, AlgorithmDescription description) { + } + + @Override + public void preProcessMotionVectors(ITexture input, ITexture output, ICommandBuffer commandBuffer, + SRShaderCompatData config, AbstractAlgorithm algorithm, AlgorithmDescription description) { + String function = IrisShaderCompatUtils.getCurrentConfig() + .map(p -> p.upscale.customs != null ? p.upscale.customs.motionVectorPreprocessingFunction : null) + .orElse(null); + if (function == null) return; + + ComputePipeline pipeline = getOrCreateMVPreprocessPipeline(function); + pipeline.descriptorSet().samplerTexture("inputMotionVectors", input); + pipeline.descriptorSet().storageImage("outputMotionVectors", output); + pipeline.descriptorSet().update(); + commandBuffer.bindPipeline(pipeline); + commandBuffer.dispatch( + (input.getWidth() + 15) / 16, + (input.getHeight() + 15) / 16, + 1 + ); + } + + private static ComputePipeline getOrCreateMVPreprocessPipeline(String function) { + ComputePipeline cached = mvPreprocessPipelineCache.get(function); + if (cached != null) return cached; + + ArrayList sourceLines = FileReadHelper.readText("/shader/interop/motion_vector_preprocess.comp.glsl"); + String templateSource = String.join("\n", sourceLines); + String modifiedSource = templateSource.replace( + "// MOTION_VECTOR_PREPROCESSING_FUNCTION_PLACEHOLDER", + function); + + ShaderSource shaderSource = new ShaderSource(ShaderType.Compute, modifiedSource, false); + ShaderDescription shaderDesc = ShaderDescription.create() + .compute(shaderSource) + .name("mv_preprocess") + .addDefine("MOTION_VECTOR_PREPROCESSING_FUNCTION_INJECTED", "1") + .uniformSamplerTexture("inputMotionVectors", 0) + .uniformStorageTexture("outputMotionVectors", 1) + .build(); + + IShaderProgram shader = RenderSystems.current().device().createShaderProgram(shaderDesc); + shader.compile(); + ComputePipeline pipeline = ComputePipeline.builder() + .shader(shader) + .build(RenderSystems.current().device()); + mvPreprocessPipelineCache.put(function, pipeline); + return pipeline; + } + + @Override + public void preProcessExposure(ITexture input, ITexture output, ICommandBuffer commandBuffer, + SRShaderCompatData config, AbstractAlgorithm algorithm, AlgorithmDescription description) { + } + + @Override + public float adaptPreExposureForAlgorithm(float rawExposure, AbstractAlgorithm algorithm, SRShaderCompatData config, AlgorithmDescription description) { + return rawExposure; + } + + + @Override + public void registerMacros(MacroRegistrar r, AbstractAlgorithm algorithm, AlgorithmDescription description) { + // region V1 + r.registerMacro("SR_INSTALLED", "1"); + + Map, Integer> idMap = new HashMap<>(); + List> algorithms = new ArrayList<>(AlgorithmRegistry.getAlgorithmMap().values()); + + AlgorithmRegistry.getAlgorithmMap().values().forEach((desc) -> { + int id = algorithms.indexOf(desc) + 0x546F0; + idMap.put(desc, id); + r.registerMacro("SR_ALGO_" + desc.codeName.toUpperCase(), Integer.toString(id)); + }); + + Arrays.stream(DLSSRenderPreset.values()).toList().forEach((preset) -> { + r.registerMacro("SR_ALGO_DLSS_RENDERPRESET_" + preset.toString(), Integer.toString(preset.getCode())); + }); + + boolean frameGenOnly = false; + SRShaderCompatData frameGenData = ShaderCompatHandler.getShaderCompatData(); + if (frameGenData != null) { + SRShaderCompatData.WorldProfile frameGenProfile = frameGenData.getProfileForWorld("*"); + if (frameGenProfile != null && frameGenProfile.upscale != null) { + frameGenOnly = frameGenProfile.upscale.onlySupportsFrameGeneration; + } + } + + if (SuperResolutionConfig.isEnableUpscaleOriginal()) { + AlgorithmDescription selectedAlgorithm = description != null + ? description + : SuperResolutionConfig.getUpscaleAlgorithm(); + r.registerMacro("SR_ENABLE", "1"); + r.registerMacro("SR_DISABLE", "0"); + r.registerMacro("SR_ALGO_SUPPORTS_JITTER", + AlgorithmManager.supportsJitter(selectedAlgorithm) ? "1" : "0"); + r.registerMacro("SR_USING_ALGO", Integer.toString( + idMap.get(selectedAlgorithm))); + r.registerMacro("SR_SHOULD_APPLY_SCALE", "1"); + r.registerMacro("SR_SHOULD_APPLY_JITTER", "1"); + r.registerMacro("SR_SCALED_WIDTH", + Integer.toString(SuperResolutionAPI.getRenderWidth())); + r.registerMacro("SR_SCALED_HEIGHT", + Integer.toString(SuperResolutionAPI.getRenderHeight())); + r.registerMacro("SR_SCREEN_WIDTH", + Integer.toString(SuperResolutionAPI.getScreenWidth())); + r.registerMacro("SR_SCREEN_HEIGHT", + Integer.toString(SuperResolutionAPI.getScreenHeight())); + r.registerMacro("SR_UPSCALE_RATIO", + Float.toString(frameGenOnly ? 1.0f : SuperResolutionConfig.getUpscaleRatio())); + r.registerMacro("SR_RENDER_SCALE_FACTOR", + Float.toString(frameGenOnly ? 1.0f : SuperResolutionConfig.getRenderScaleFactor())); + + r.registerMacro("SR_JITTER_SEQUENCE_LENGTH", + Integer.toString(AlgorithmManager.getConfiguredJitterSequenceLength())); + r.registerMacro("SR_ALGO_DLSS_RENDERPRESET", + selectedAlgorithm.equals(AlgorithmDescriptions.DLSS) ? + Integer.toString(SuperResolutionConfig.SPECIAL.DLSS.RENDER_PRESET.get().getCode()) : + "0"); + } else { + r.registerMacro("SR_ENABLE", "0"); + r.registerMacro("SR_DISABLE", "1"); + r.registerMacro("SR_ALGO_SUPPORTS_JITTER", "0"); + r.registerMacro("SR_USING_ALGO", "0"); + r.registerMacro("SR_SHOULD_APPLY_SCALE", "0"); + r.registerMacro("SR_SHOULD_APPLY_JITTER", "0"); + r.registerMacro("SR_SCALED_WIDTH", + Integer.toString(SuperResolutionAPI.getScreenWidth())); + r.registerMacro("SR_SCALED_HEIGHT", + Integer.toString(SuperResolutionAPI.getScreenHeight())); + r.registerMacro("SR_SCREEN_WIDTH", + Integer.toString(SuperResolutionAPI.getScreenWidth())); + r.registerMacro("SR_SCREEN_HEIGHT", + Integer.toString(SuperResolutionAPI.getScreenHeight())); + r.registerMacro("SR_UPSCALE_RATIO", + Float.toString(1.0f)); + r.registerMacro("SR_RENDER_SCALE_FACTOR", + Float.toString(1.0f)); + r.registerMacro("SR_JITTER_SEQUENCE_LENGTH", "0"); + } + // endregion + + // region V2 + if (SuperResolutionConfig.isEnableUpscaleOriginal()) { + float rsf = frameGenOnly ? 1.0f : SuperResolutionConfig.getRenderScaleFactor(); + float ratio = frameGenOnly ? 1.0f : SuperResolutionConfig.getUpscaleRatio(); + r.registerMacro("SR_UPSCALE_RATIO_HALF", + Float.toString(ratio * 0.5F)); + r.registerMacro("SR_RENDER_SCALE_FACTOR_HALF", + Float.toString(rsf * 0.5F)); + } else { + r.registerMacro("SR_UPSCALE_RATIO_HALF", + Float.toString(0.5F)); + r.registerMacro("SR_RENDER_SCALE_FACTOR_HALF", + Float.toString(0.5F)); + } + // endregion + + // region V3 + r.registerMacro("SR_CONFIG_SCHEMA_VERSION", "3"); + // endregion + } + + @Override + public void registerUniforms(UniformRegistrar r, SRShaderCompatData config, AbstractAlgorithm algorithm, AlgorithmDescription description) { + // region V1 + r.uniform1f("SRRenderScale", + () -> SuperResolutionConfig.isEnableUpscaleOriginal() ? SuperResolutionConfig.getRenderScaleFactor() : 1); + r.uniform1f("SRRatio", + () -> SuperResolutionConfig.isEnableUpscaleOriginal() ? SuperResolutionConfig.getUpscaleRatio() : 1); + r.uniform1f("SRRenderScaleLog2", + () -> SuperResolutionConfig.isEnableUpscaleOriginal() + ? (float) (Math.log((double) SuperResolutionAPI.getRenderWidth() / + SuperResolutionAPI.getScreenWidth()) / Math.log(2)) + : 0); + r.uniform1i("SRFrameCount", RenderHandlerManager::getFrameCount); + r.uniform2f("SRScaledViewportSize", + () -> new Vector2f(RenderHandlerManager.getRenderWidth(), RenderHandlerManager.getRenderHeight())); + r.uniform2f("SROriginalViewportSize", + () -> new Vector2f(RenderHandlerManager.getScreenWidth(), RenderHandlerManager.getScreenHeight())); + r.uniform2i("SRScaledViewportSizeI", + () -> new Vector2i(RenderHandlerManager.getRenderWidth(), RenderHandlerManager.getRenderHeight())); + r.uniform2i("SROriginalViewportSizeI", + () -> new Vector2i(RenderHandlerManager.getScreenWidth(), RenderHandlerManager.getScreenHeight())); + + Optional currentConfig = IrisShaderCompatUtils.getCurrentConfig(); + if (!(currentConfig.isEmpty() || currentConfig.get().jitter.source == SRShaderCompatData.JitterConfig.JitterSource.SHADERPACK)) { + r.uniform2f("SRJitterOffset", + () -> { + if (description == null || !description.isSupportJitter()) { + return new Vector2f(0); + } + Vector2f rawJitter = IrisShaderCompatUpscaleDispatcher.getJitterOffset(); + return adaptJitterForShaderpack(rawJitter, algorithm, config, description); + }); + r.uniform2f("SRPreviousJitterOffset", + () -> { + if (description == null + || !description.isSupportJitter() + || IrisShaderCompatUtils.getCurrentConfig().isEmpty() + || IrisShaderCompatUtils.getCurrentConfig().get().jitter.source != SRShaderCompatData.JitterConfig.JitterSource.MOD) { + return new Vector2f(0); + } + Vector2f rawJitter = AlgorithmManager.getPreviousJitterOffset(); + return adaptJitterForShaderpack(rawJitter, algorithm, config, description); + }); + } + // endregion + } +} diff --git a/common/src/shadercompat/java/io/homo/superresolution/shadercompat/IrisShaderCompatUpscaleDispatcher.java b/common/src/shadercompat/java/io/homo/superresolution/shadercompat/IrisShaderCompatUpscaleDispatcher.java index 3be8a6b7..366d660f 100644 --- a/common/src/shadercompat/java/io/homo/superresolution/shadercompat/IrisShaderCompatUpscaleDispatcher.java +++ b/common/src/shadercompat/java/io/homo/superresolution/shadercompat/IrisShaderCompatUpscaleDispatcher.java @@ -36,6 +36,7 @@ import io.homo.superresolution.common.minecraft.handler.shadercompat.SRShaderCompatData; import io.homo.superresolution.common.minecraft.handler.shadercompat.ShaderCompatTextureInfo; import io.homo.superresolution.common.minecraft.handler.shadercompat.v2.SRCompatV2Processor; +import io.homo.superresolution.common.minecraft.handler.shadercompat.v3.SRCompatV3Processor; import io.homo.superresolution.common.perf.PerformanceTracker; import io.homo.superresolution.common.upscale.AlgorithmManager; import io.homo.superresolution.common.upscale.DispatchResource; @@ -249,6 +250,7 @@ public static void reset(){ RenderHandlerManager.frameCount = 0; InteropResourcesConverter.destroy(); SRCompatV2Processor.destroyPipelineCache(); + SRCompatV3Processor.destroyPipelineCache(); } public static void dispatchUpscale(ICompositeRendererAccessor compositeRenderer, NamedCompositePass pass) { @@ -395,14 +397,14 @@ public static void dispatchUpscale(ICompositeRendererAccessor compositeRenderer, /* 升采样阶段开始 */ - { + boolean frameGenOnly = currentConfig.onlySupportsFrameGeneration; + if (!frameGenOnly) { if (RenderHandlerManager.needCaptureUpscale) { if (RenderDoc.renderdoc != null) { RenderDoc.renderdoc.StartFrameCapture.call(null, null); } } } - GlDebug.pushGroup(64108436, "SR Upscale"); AlgorithmManager.update(); // MotionVectorsGenerator 已被弃用 Vector2f rawJitter = getJitterOffset(); @@ -426,8 +428,12 @@ public static void dispatchUpscale(ICompositeRendererAccessor compositeRenderer, ) ); } - try (GlState ignored_ = new GlState()) { - SuperResolution.getCurrentAlgorithm().dispatch(dispatchResource); + if (!frameGenOnly) { + GlDebug.pushGroup(64108436, "SR Upscale"); + try (GlState ignored_ = new GlState()) { + SuperResolution.getCurrentAlgorithm().dispatch(dispatchResource); + } + GlDebug.popGroup(); } if (SuperResolution.currentAlgorithm != null) { SuperResolutionAPI.EVENT_BUS.post( @@ -437,13 +443,13 @@ public static void dispatchUpscale(ICompositeRendererAccessor compositeRenderer, ) ); } - GlDebug.popGroup(); /* 升采样阶段结束 */ - GlDebug.pushGroup(64108436, "SRUpscale-CopyResult"); - IFrameBuffer outFbo = SuperResolution.getCurrentAlgorithm().getOutputFrameBuffer(); - if (currentConfig.outputTextures.get("upscaled_color").enabled) { + if (!frameGenOnly) { + GlDebug.pushGroup(64108436, "SRUpscale-CopyResult"); + IFrameBuffer outFbo = SuperResolution.getCurrentAlgorithm().getOutputFrameBuffer(); + if (currentConfig.outputTextures.get("upscaled_color").enabled) { for (String targetName : currentConfig.outputTextures.get("upscaled_color").targetNames) { ITexture targetTexture = cachedOutputTargetTextures.computeIfAbsent(targetName, name -> IrisTextureResolver.getIrisTexture( @@ -486,14 +492,15 @@ public static void dispatchUpscale(ICompositeRendererAccessor compositeRenderer, ); } } + } } - } - GlDebug.popGroup(); - { - if (RenderHandlerManager.needCaptureUpscale) { - if (RenderDoc.renderdoc != null) { - RenderHandlerManager.needCaptureUpscale = false; - RenderDoc.renderdoc.EndFrameCapture.call(null, null); + GlDebug.popGroup(); + { + if (RenderHandlerManager.needCaptureUpscale) { + if (RenderDoc.renderdoc != null) { + RenderHandlerManager.needCaptureUpscale = false; + RenderDoc.renderdoc.EndFrameCapture.call(null, null); + } } } } diff --git a/common/src/shadercompat/java/io/homo/superresolution/shadercompat/ShaderCompatSRWorkModeProvider.java b/common/src/shadercompat/java/io/homo/superresolution/shadercompat/ShaderCompatSRWorkModeProvider.java index b8b92951..3d32d3e1 100644 --- a/common/src/shadercompat/java/io/homo/superresolution/shadercompat/ShaderCompatSRWorkModeProvider.java +++ b/common/src/shadercompat/java/io/homo/superresolution/shadercompat/ShaderCompatSRWorkModeProvider.java @@ -12,6 +12,8 @@ import io.homo.superresolution.common.workmode.SRWorkModeState; import io.homo.superresolution.core.graphics.impl.texture.TextureFormat; +import java.util.Collections; +import java.util.List; import java.util.Optional; public class ShaderCompatSRWorkModeProvider implements SRWorkModeProvider { @@ -59,12 +61,20 @@ public SRWorkModeState getState() { } } + List disabledAlgorithms = Collections.emptyList(); + if (profile.isPresent() && profile.get().enabled && profile.get().upscale != null) { + disabledAlgorithms = profile.get().upscale.disabledAlgorithms; + } + return new SRWorkModeState( desc, internalFormat, motionVectorPreprocessingFunction, ShaderCompatHandler.irisApiIsShaderPackInUse() || ShaderCompatHandler.irisHasShaderPack(), - ShaderCompatHandler.isLoadingShader() + ShaderCompatHandler.isLoadingShader(), + profile.isPresent() && profile.get().enabled && profile.get().upscale != null && + profile.get().upscale.onlySupportsFrameGeneration, + disabledAlgorithms ); }