shader_recompiler: Add stubs for CSM/FCSM flow test conditions

Add stub implementations for previously unhandled flow test conditions in the
shader recompiler's IR emitter. These conditions were previously throwing
"Not Implemented" exceptions when encountered.

The following flow test cases are now stubbed:
- FCSM_TR (Fragment Shader Coarse/Fine Mode Test and Reject)
- CSM_TA (Coarse/Fine Mode Test Accept)
- CSM_TR (Coarse/Fine Mode Test and Reject)
- CSM_MX (Coarse/Fine Mode Maximum)
- FCSM_TA (Fragment Shader Coarse/Fine Mode Test Accept)
- FCSM_MX (Fragment Shader Coarse/Fine Mode Maximum)

Currently these stubs:
1. Return false (ir.Imm1(false)) as a placeholder value
2. Log a warning message indicating the stub
3. Allow shaders using these conditions to compile rather than fail

This is a step toward proper implementation of coarse/fine mode shader
operations. The stubs prevent crashes while making it clear which code paths
need full implementation.

Technical notes:
- Removed the previous FCSM_TR implementation that used flag operations
- Added consistent warning messages for tracking stub usage
- Kept within the existing GetFlowTest switch statement structure
This commit is contained in:
Zephyron 2025-01-17 19:28:11 +10:00
parent ee0beea82a
commit 382999025a
30 changed files with 128 additions and 112 deletions

View file

@ -10,6 +10,7 @@ import android.content.DialogInterface
import android.content.pm.ActivityInfo
import android.content.res.Configuration
import android.net.Uri
import android.os.BatteryManager
import android.os.Bundle
import android.os.Handler
import android.os.Looper
@ -531,59 +532,8 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
if (emulationViewModel.emulationStarted.value &&
!emulationViewModel.isEmulationStopping.value
) {
val thermalStatus = when (powerManager.currentThermalStatus) {
PowerManager.THERMAL_STATUS_LIGHT -> 0.25f
PowerManager.THERMAL_STATUS_MODERATE -> 0.5f
PowerManager.THERMAL_STATUS_SEVERE -> 0.75f
PowerManager.THERMAL_STATUS_CRITICAL,
PowerManager.THERMAL_STATUS_EMERGENCY,
PowerManager.THERMAL_STATUS_SHUTDOWN -> 1.0f
else -> 0f
}
// Get temperature from battery thermal sensor
val temperature = try {
val process = Runtime.getRuntime().exec("cat /sys/class/power_supply/battery/temp")
val reader = process.inputStream.bufferedReader()
val temp = reader.readLine().toFloat() / 10f // Convert from decidegrees to degrees
reader.close()
temp
} catch (e: Exception) {
0f
}
// Convert to Fahrenheit
val fahrenheit = (temperature * 9f / 5f) + 32f
if (_binding != null) {
// Color interpolation based on temperature (green at 30°C, red at 45°C)
val normalizedTemp = ((temperature - 30f) / 15f).coerceIn(0f, 1f)
val red = (normalizedTemp * 255).toInt()
val green = ((1f - normalizedTemp) * 255).toInt()
val color = android.graphics.Color.rgb(red, green, 0)
// Create a modern progress bar using block elements
val progressBarLength = 12
val filledBars = (thermalStatus * progressBarLength).toInt()
val progressBar = buildString {
append("") // Left border
repeat(filledBars) { append("") }
repeat(progressBarLength - filledBars) { append("") }
append("") // Right border
// Add percentage
append(" ")
append(String.format("%3d%%", (thermalStatus * 100).toInt()))
}
binding.showThermalsText.setTextColor(color)
binding.showThermalsText.text = String.format(
"%s\n%.1f°C • %.1f°F",
progressBar,
temperature,
fahrenheit
)
}
val temperature = getBatteryTemperature(requireContext())
updateThermalOverlay(temperature)
thermalStatsUpdateHandler.postDelayed(thermalStatsUpdater!!, 1000)
}
}
@ -595,6 +545,53 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
}
}
private fun updateThermalOverlay(temperature: Float) {
if (BooleanSetting.SHOW_THERMAL_OVERLAY.getBoolean() &&
emulationViewModel.emulationStarted.value &&
!emulationViewModel.isEmulationStopping.value
) {
// Get thermal status
val thermalStatus = when (powerManager.currentThermalStatus) {
PowerManager.THERMAL_STATUS_LIGHT -> 0.25f
PowerManager.THERMAL_STATUS_MODERATE -> 0.5f
PowerManager.THERMAL_STATUS_SEVERE -> 0.75f
PowerManager.THERMAL_STATUS_CRITICAL,
PowerManager.THERMAL_STATUS_EMERGENCY,
PowerManager.THERMAL_STATUS_SHUTDOWN -> 1.0f
else -> 0f
}
// Convert to Fahrenheit for additional info
val fahrenheit = (temperature * 9f / 5f) + 32f
// Create progress bar using block elements
val progressBarLength = 12
val filledBars = (thermalStatus * progressBarLength).toInt()
val progressBar = buildString {
append("") // Left border
repeat(filledBars) { append("") }
repeat(progressBarLength - filledBars) { append("") }
append("") // Right border
append(" ")
append(String.format("%3d%%", (thermalStatus * 100).toInt()))
}
// Color interpolation based on temperature (green at 30°C, red at 45°C)
val normalizedTemp = ((temperature - 30f) / 15f).coerceIn(0f, 1f)
val red = (normalizedTemp * 255).toInt()
val green = ((1f - normalizedTemp) * 255).toInt()
val color = android.graphics.Color.rgb(red, green, 0)
binding.showThermalsText.setTextColor(color)
binding.showThermalsText.text = String.format(
"%s\n%.1f°C • %.1f°F",
progressBar,
temperature,
fahrenheit
)
}
}
@SuppressLint("SourceLockedOrientationActivity")
private fun updateOrientation() {
emulationActivity?.let {
@ -1095,4 +1092,12 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
private val perfStatsUpdateHandler = Handler(Looper.myLooper()!!)
private val thermalStatsUpdateHandler = Handler(Looper.myLooper()!!)
}
private fun getBatteryTemperature(context: Context): Float {
val batteryManager = context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager
// Get temperature in tenths of a degree Celsius
val temperature = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_TEMPERATURE)
// Convert to degrees Celsius
return temperature / 10.0f
}
}

View file

@ -34,7 +34,7 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QWidget* parent) {
INSERT(Settings, net_connect_applet_mode, tr("Net connect"), QStringLiteral());
INSERT(Settings, player_select_applet_mode, tr("Player select"), QStringLiteral());
INSERT(Settings, swkbd_applet_mode, tr("Software keyboard"), QStringLiteral());
INSERT(Settings, mii_edit_applet_mode, tr("Mii Edit"), QStringLiteral());
INSERT(Settings, mii_edit_applet_mode, tr("Mii Editor"), QStringLiteral());
INSERT(Settings, web_applet_mode, tr("Online web"), QStringLiteral());
INSERT(Settings, shop_applet_mode, tr("Shop"), QStringLiteral());
INSERT(Settings, photo_viewer_applet_mode, tr("Photo viewer"), QStringLiteral());

View file

@ -4445,7 +4445,7 @@ void GMainWindow::OnMiiEdit() {
auto mii_applet_nca = bis_system->GetEntry(MiiEditId, FileSys::ContentRecordType::Program);
if (!mii_applet_nca) {
QMessageBox::warning(this, tr("Mii Edit Applet"),
QMessageBox::warning(this, tr("Mii Editor Applet"),
tr("Mii editor is not available. Please reinstall firmware."));
return;
}

View file

@ -261,12 +261,23 @@ static U1 GetFlowTest(IREmitter& ir, FlowTest flow_test) {
case FlowTest::RGT:
return ir.LogicalAnd(ir.LogicalNot(ir.GetSFlag()), ir.LogicalNot(ir.GetZFlag()));
case FlowTest::FCSM_TR:
return ir.LogicalAnd(ir.GetSFlag(), ir.LogicalNot(ir.GetZFlag()));
LOG_WARNING(Shader, "(STUBBED) FCSM_TR");
return ir.Imm1(false);
case FlowTest::CSM_TA:
LOG_WARNING(Shader, "(STUBBED) CSM_TA");
return ir.Imm1(false);
case FlowTest::CSM_TR:
LOG_WARNING(Shader, "(STUBBED) CSM_TR");
return ir.Imm1(false);
case FlowTest::CSM_MX:
LOG_WARNING(Shader, "(STUBBED) CSM_MX");
return ir.Imm1(false);
case FlowTest::FCSM_TA:
LOG_WARNING(Shader, "(STUBBED) FCSM_TA");
return ir.Imm1(false);
case FlowTest::FCSM_MX:
LOG_WARNING(Shader, "(STUBBED) FCSM_MX");
return ir.Imm1(false);
default:
throw NotImplementedException("Flow test {}", flow_test);
}