summaryrefslogtreecommitdiff
path: root/py_modules/lsfg_vk/config_schema.py
diff options
context:
space:
mode:
authorxXJSONDeruloXx <danielhimebauch@gmail.com>2025-07-16 13:54:09 -0400
committerxXJSONDeruloXx <danielhimebauch@gmail.com>2025-07-16 13:54:09 -0400
commit7868396718b13443209e7c5d83a2c96cd7eee31e (patch)
tree96e8e172c4484caecca591174a3dea2e5d8da363 /py_modules/lsfg_vk/config_schema.py
parent41bba67d24241dea18b056734b153270bb230ba1 (diff)
downloaddecky-lsfg-vk-7868396718b13443209e7c5d83a2c96cd7eee31e.tar.gz
decky-lsfg-vk-7868396718b13443209e7c5d83a2c96cd7eee31e.zip
centralized configuration system for lsfg-vk params
Diffstat (limited to 'py_modules/lsfg_vk/config_schema.py')
-rw-r--r--py_modules/lsfg_vk/config_schema.py228
1 files changed, 228 insertions, 0 deletions
diff --git a/py_modules/lsfg_vk/config_schema.py b/py_modules/lsfg_vk/config_schema.py
new file mode 100644
index 0000000..0f1bdae
--- /dev/null
+++ b/py_modules/lsfg_vk/config_schema.py
@@ -0,0 +1,228 @@
+"""
+Centralized configuration schema for lsfg-vk.
+
+This module defines the complete configuration structure, including:
+- Field definitions with types, defaults, and metadata
+- Script generation logic
+- Validation rules
+- Type definitions
+"""
+
+from typing import TypedDict, Dict, Any, Union, Callable, cast
+from dataclasses import dataclass, field
+from enum import Enum
+
+
+class ConfigFieldType(Enum):
+ """Supported configuration field types"""
+ BOOLEAN = "boolean"
+ INTEGER = "integer"
+ FLOAT = "float"
+
+
+@dataclass
+class ConfigField:
+ """Configuration field definition"""
+ name: str
+ field_type: ConfigFieldType
+ default: Union[bool, int, float]
+ description: str
+ script_template: str # Template for script generation
+ script_comment: str = "" # Comment to add when disabled
+
+ def get_script_line(self, value: Union[bool, int, float]) -> str:
+ """Generate script line for this field"""
+ if self.field_type == ConfigFieldType.BOOLEAN:
+ if value:
+ return self.script_template.format(value=1)
+ else:
+ return f"# {self.script_template.format(value=1)}"
+ else:
+ return self.script_template.format(value=value)
+
+
+# Configuration schema definition
+CONFIG_SCHEMA: Dict[str, ConfigField] = {
+ "enable_lsfg": ConfigField(
+ name="enable_lsfg",
+ field_type=ConfigFieldType.BOOLEAN,
+ default=True,
+ description="Enables the frame generation layer",
+ script_template="export ENABLE_LSFG={value}",
+ script_comment="# export ENABLE_LSFG=1"
+ ),
+
+ "multiplier": ConfigField(
+ name="multiplier",
+ field_type=ConfigFieldType.INTEGER,
+ default=2,
+ description="Traditional FPS multiplier value",
+ script_template="export LSFG_MULTIPLIER={value}"
+ ),
+
+ "flow_scale": ConfigField(
+ name="flow_scale",
+ field_type=ConfigFieldType.FLOAT,
+ default=0.8,
+ description="Lowers the internal motion estimation resolution",
+ script_template="export LSFG_FLOW_SCALE={value}"
+ ),
+
+ "hdr": ConfigField(
+ name="hdr",
+ field_type=ConfigFieldType.BOOLEAN,
+ default=False,
+ description="Enable HDR mode (only if Game supports HDR)",
+ script_template="export LSFG_HDR={value}",
+ script_comment="# export LSFG_HDR=1"
+ ),
+
+ "perf_mode": ConfigField(
+ name="perf_mode",
+ field_type=ConfigFieldType.BOOLEAN,
+ default=True,
+ description="Use lighter model for FG",
+ script_template="export LSFG_PERF_MODE={value}",
+ script_comment="# export LSFG_PERF_MODE=1"
+ ),
+
+ "immediate_mode": ConfigField(
+ name="immediate_mode",
+ field_type=ConfigFieldType.BOOLEAN,
+ default=False,
+ description="Reduce input lag (Experimental, will cause issues in many games)",
+ script_template="export MESA_VK_WSI_PRESENT_MODE=immediate # - disable vsync",
+ script_comment="# export MESA_VK_WSI_PRESENT_MODE=immediate # - disable vsync"
+ ),
+
+ "disable_vkbasalt": ConfigField(
+ name="disable_vkbasalt",
+ field_type=ConfigFieldType.BOOLEAN,
+ default=True,
+ description="Some plugins add vkbasalt layer, which can break lsfg. Toggling on fixes this",
+ script_template="export DISABLE_VKBASALT={value}",
+ script_comment="# export DISABLE_VKBASALT=1"
+ ),
+
+ "frame_cap": ConfigField(
+ name="frame_cap",
+ field_type=ConfigFieldType.INTEGER,
+ default=0,
+ description="Limit base game FPS (0 = disabled)",
+ script_template="export DXVK_FRAME_RATE={value}",
+ script_comment="# export DXVK_FRAME_RATE=60"
+ )
+}
+
+
+class ConfigurationData(TypedDict):
+ """Type-safe configuration data structure"""
+ enable_lsfg: bool
+ multiplier: int
+ flow_scale: float
+ hdr: bool
+ perf_mode: bool
+ immediate_mode: bool
+ disable_vkbasalt: bool
+ frame_cap: int
+
+
+class ConfigurationManager:
+ """Centralized configuration management"""
+
+ @staticmethod
+ def get_defaults() -> ConfigurationData:
+ """Get default configuration values"""
+ return cast(ConfigurationData, {
+ field.name: field.default
+ for field in CONFIG_SCHEMA.values()
+ })
+
+ @staticmethod
+ def get_field_names() -> list[str]:
+ """Get ordered list of configuration field names"""
+ return list(CONFIG_SCHEMA.keys())
+
+ @staticmethod
+ def get_field_types() -> Dict[str, ConfigFieldType]:
+ """Get field type mapping"""
+ return {
+ field.name: field.field_type
+ for field in CONFIG_SCHEMA.values()
+ }
+
+ @staticmethod
+ def validate_config(config: Dict[str, Any]) -> ConfigurationData:
+ """Validate and convert configuration data"""
+ validated = {}
+
+ for field_name, field_def in CONFIG_SCHEMA.items():
+ value = config.get(field_name, field_def.default)
+
+ # Type validation and conversion
+ if field_def.field_type == ConfigFieldType.BOOLEAN:
+ validated[field_name] = bool(value)
+ elif field_def.field_type == ConfigFieldType.INTEGER:
+ validated[field_name] = int(value)
+ elif field_def.field_type == ConfigFieldType.FLOAT:
+ validated[field_name] = float(value)
+ else:
+ validated[field_name] = value
+
+ return cast(ConfigurationData, validated)
+
+ @staticmethod
+ def generate_script_content(config: ConfigurationData) -> str:
+ """Generate lsfg script content from configuration"""
+ script_lines = ["#!/bin/bash", ""]
+
+ # Generate script lines for each field
+ for field_name in CONFIG_SCHEMA.keys():
+ field_def = CONFIG_SCHEMA[field_name]
+ value = config[field_name]
+
+ if field_def.field_type == ConfigFieldType.BOOLEAN:
+ if value:
+ script_lines.append(field_def.script_template.format(value=1))
+ else:
+ script_lines.append(field_def.script_comment)
+ else:
+ # For frame_cap, special handling for 0 value
+ if field_name == "frame_cap" and value == 0:
+ script_lines.append(field_def.script_comment)
+ else:
+ script_lines.append(field_def.script_template.format(value=value))
+
+ # Add script footer
+ script_lines.extend([
+ "",
+ "# Execute the passed command with the environment variables set",
+ 'exec "$@"'
+ ])
+
+ return "\n".join(script_lines)
+
+ @staticmethod
+ def get_update_signature() -> list[tuple[str, type]]:
+ """Get the function signature for update_config method"""
+ signature = []
+ for field_name, field_def in CONFIG_SCHEMA.items():
+ if field_def.field_type == ConfigFieldType.BOOLEAN:
+ signature.append((field_name, bool))
+ elif field_def.field_type == ConfigFieldType.INTEGER:
+ signature.append((field_name, int))
+ elif field_def.field_type == ConfigFieldType.FLOAT:
+ signature.append((field_name, float))
+ return signature
+
+ @staticmethod
+ def create_config_from_args(*args) -> ConfigurationData:
+ """Create configuration from ordered arguments"""
+ field_names = ConfigurationManager.get_field_names()
+ if len(args) != len(field_names):
+ raise ValueError(f"Expected {len(field_names)} arguments, got {len(args)}")
+
+ return cast(ConfigurationData, {
+ field_name: args[i]
+ for i, field_name in enumerate(field_names)
+ })