mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-29 13:45:29 +03:00
Add Performance Statistics to EmulationActivity
This commit adds performance statistics to the emulator that can be toggled in preferences. The layout of `EmulationActivity` was also changed from `ConstraintLayout` to `RelativeLayout` due to poor performance of the former.
This commit is contained in:
parent
fb1a158e8f
commit
7f78a679c3
@ -11,6 +11,8 @@ bool Halt;
|
|||||||
jobject Surface;
|
jobject Surface;
|
||||||
uint FaultCount;
|
uint FaultCount;
|
||||||
skyline::GroupMutex JniMtx;
|
skyline::GroupMutex JniMtx;
|
||||||
|
skyline::u16 fps;
|
||||||
|
skyline::u32 frametime;
|
||||||
|
|
||||||
void signalHandler(int signal) {
|
void signalHandler(int signal) {
|
||||||
syslog(LOG_ERR, "Halting program due to signal: %s", strsignal(signal));
|
syslog(LOG_ERR, "Halting program due to signal: %s", strsignal(signal));
|
||||||
@ -74,3 +76,11 @@ extern "C" JNIEXPORT void Java_emu_skyline_EmulationActivity_setSurface(JNIEnv *
|
|||||||
Surface = surface;
|
Surface = surface;
|
||||||
JniMtx.unlock();
|
JniMtx.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT jint Java_emu_skyline_EmulationActivity_getFps(JNIEnv *env, jobject thiz) {
|
||||||
|
return fps;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT jfloat Java_emu_skyline_EmulationActivity_getFrametime(JNIEnv *env, jobject thiz) {
|
||||||
|
return static_cast<float>(frametime) / 100;
|
||||||
|
}
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
extern bool Halt;
|
extern bool Halt;
|
||||||
extern jobject Surface;
|
extern jobject Surface;
|
||||||
|
extern skyline::u16 fps;
|
||||||
|
extern skyline::u32 frametime;
|
||||||
|
|
||||||
namespace skyline::gpu {
|
namespace skyline::gpu {
|
||||||
GPU::GPU(const DeviceState &state) : state(state), window(ANativeWindow_fromSurface(state.jvm->GetEnv(), Surface)), vsyncEvent(std::make_shared<kernel::type::KEvent>(state)), bufferEvent(std::make_shared<kernel::type::KEvent>(state)) {
|
GPU::GPU(const DeviceState &state) : state(state), window(ANativeWindow_fromSurface(state.jvm->GetEnv(), Surface)), vsyncEvent(std::make_shared<kernel::type::KEvent>(state)), bufferEvent(std::make_shared<kernel::type::KEvent>(state)) {
|
||||||
@ -57,12 +59,16 @@ namespace skyline::gpu {
|
|||||||
vsyncEvent->Signal();
|
vsyncEvent->Signal();
|
||||||
texture->releaseCallback();
|
texture->releaseCallback();
|
||||||
|
|
||||||
if (prevTime != 0) {
|
if (frameTimestamp) {
|
||||||
auto now = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
|
auto now = util::GetTimeNs();
|
||||||
state.logger->Error("{} ms, {} FPS", (now - prevTime) / 1000, 1000000 / (now - prevTime));
|
|
||||||
}
|
|
||||||
|
|
||||||
prevTime = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
|
frametime = static_cast<u32>((now - frameTimestamp) / 10000); // frametime / 100 is the real ms value, this is to retain the first two decimals
|
||||||
|
fps = static_cast<u16>(1000000000 / (now - frameTimestamp));
|
||||||
|
|
||||||
|
frameTimestamp = now;
|
||||||
|
} else {
|
||||||
|
frameTimestamp = util::GetTimeNs();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ namespace skyline::gpu {
|
|||||||
ANativeWindow *window; //!< The ANativeWindow to render to
|
ANativeWindow *window; //!< The ANativeWindow to render to
|
||||||
const DeviceState &state; //!< The state of the device
|
const DeviceState &state; //!< The state of the device
|
||||||
bool surfaceUpdate{}; //!< If the surface needs to be updated
|
bool surfaceUpdate{}; //!< If the surface needs to be updated
|
||||||
double prevTime{}; //!< The time passed from the last frame
|
u64 frameTimestamp{}; //!< The timestamp of the last frame being shown
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::queue<std::shared_ptr<PresentationTexture>> presentationQueue; //!< A queue of all the PresentationTextures to be posted to the display
|
std::queue<std::shared_ptr<PresentationTexture>> presentationQueue; //!< A queue of all the PresentationTextures to be posted to the display
|
||||||
|
@ -14,8 +14,9 @@ import android.view.Surface
|
|||||||
import android.view.SurfaceHolder
|
import android.view.SurfaceHolder
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.preference.PreferenceManager
|
||||||
import emu.skyline.loader.getRomFormat
|
import emu.skyline.loader.getRomFormat
|
||||||
import kotlinx.android.synthetic.main.app_activity.*
|
import kotlinx.android.synthetic.main.emu_activity.*
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback {
|
class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback {
|
||||||
@ -78,6 +79,16 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback {
|
|||||||
*/
|
*/
|
||||||
private external fun setSurface(surface: Surface?)
|
private external fun setSurface(surface: Surface?)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This returns the current FPS of the application
|
||||||
|
*/
|
||||||
|
private external fun getFps(): Int
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This returns the current frame-time of the application
|
||||||
|
*/
|
||||||
|
private external fun getFrametime(): Float
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This executes the specified ROM, [preferenceFd] and [logFd] are assumed to be valid beforehand
|
* This executes the specified ROM, [preferenceFd] and [logFd] are assumed to be valid beforehand
|
||||||
*
|
*
|
||||||
@ -101,12 +112,14 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This sets up [preferenceFd] and [logFd] then calls [executeApplication] for executing the application
|
* This makes the window fullscreen then sets up [preferenceFd] and [logFd], sets up the performance statistics and finally calls [executeApplication] for executing the application
|
||||||
*/
|
*/
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
setContentView(R.layout.app_activity)
|
setContentView(R.layout.emu_activity)
|
||||||
|
|
||||||
|
window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN)
|
||||||
|
|
||||||
val preference = File("${applicationInfo.dataDir}/shared_prefs/${applicationInfo.packageName}_preferences.xml")
|
val preference = File("${applicationInfo.dataDir}/shared_prefs/${applicationInfo.packageName}_preferences.xml")
|
||||||
preferenceFd = ParcelFileDescriptor.open(preference, ParcelFileDescriptor.MODE_READ_WRITE)
|
preferenceFd = ParcelFileDescriptor.open(preference, ParcelFileDescriptor.MODE_READ_WRITE)
|
||||||
@ -114,9 +127,21 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback {
|
|||||||
val log = File("${applicationInfo.dataDir}/skyline.log")
|
val log = File("${applicationInfo.dataDir}/skyline.log")
|
||||||
logFd = ParcelFileDescriptor.open(log, ParcelFileDescriptor.MODE_CREATE or ParcelFileDescriptor.MODE_READ_WRITE)
|
logFd = ParcelFileDescriptor.open(log, ParcelFileDescriptor.MODE_CREATE or ParcelFileDescriptor.MODE_READ_WRITE)
|
||||||
|
|
||||||
window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN)
|
|
||||||
game_view.holder.addCallback(this)
|
game_view.holder.addCallback(this)
|
||||||
|
|
||||||
|
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
|
||||||
|
|
||||||
|
if (sharedPreferences.getBoolean("perf_stats", false)) {
|
||||||
|
lateinit var perfRunnable: Runnable
|
||||||
|
|
||||||
|
perfRunnable = Runnable {
|
||||||
|
perf_stats.text = "${getFps()} FPS\n${getFrametime()}ms"
|
||||||
|
perf_stats.postDelayed(perfRunnable, 250)
|
||||||
|
}
|
||||||
|
|
||||||
|
perf_stats.postDelayed(perfRunnable, 250)
|
||||||
|
}
|
||||||
|
|
||||||
executeApplication(intent.data!!)
|
executeApplication(intent.data!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
tools:context=".EmulationActivity">
|
|
||||||
|
|
||||||
<SurfaceView
|
|
||||||
android:id="@+id/game_view"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
25
app/src/main/res/layout/emu_activity.xml
Normal file
25
app/src/main/res/layout/emu_activity.xml
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:context=".EmulationActivity">
|
||||||
|
|
||||||
|
<SurfaceView
|
||||||
|
android:id="@+id/game_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_alignParentStart="true"
|
||||||
|
android:layout_alignParentTop="true" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/perf_stats"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentStart="true"
|
||||||
|
android:layout_alignParentTop="true"
|
||||||
|
android:layout_marginStart="5dp"
|
||||||
|
android:layout_marginTop="5dp"
|
||||||
|
android:textColor="#5fffffff" />
|
||||||
|
|
||||||
|
</RelativeLayout>
|
@ -32,7 +32,7 @@
|
|||||||
<string name="log_level">Log Level</string>
|
<string name="log_level">Log Level</string>
|
||||||
<string name="log_compact">Compact Logs</string>
|
<string name="log_compact">Compact Logs</string>
|
||||||
<string name="log_compact_desc_on">Logs will be displayed in a compact form factor</string>
|
<string name="log_compact_desc_on">Logs will be displayed in a compact form factor</string>
|
||||||
<string name="log_compact_desc_off">The logs will be displayed in a verbose form factor</string>
|
<string name="log_compact_desc_off">Logs will be displayed in a verbose form factor</string>
|
||||||
<string name="system">System</string>
|
<string name="system">System</string>
|
||||||
<string name="use_docked">Use Docked Mode</string>
|
<string name="use_docked">Use Docked Mode</string>
|
||||||
<string name="handheld_enabled">The system will emulate being in handheld mode</string>
|
<string name="handheld_enabled">The system will emulate being in handheld mode</string>
|
||||||
@ -59,4 +59,7 @@
|
|||||||
<string name="ktstd_description">We use Kotlin Standard Library for accessing convenience functions in Kotlin (Apache License 2.0)</string>
|
<string name="ktstd_description">We use Kotlin Standard Library for accessing convenience functions in Kotlin (Apache License 2.0)</string>
|
||||||
<string name="mtico">Material Design Icons</string>
|
<string name="mtico">Material Design Icons</string>
|
||||||
<string name="mtico_description">We use Material Design Icons to have consistent iconography throughout the application</string>
|
<string name="mtico_description">We use Material Design Icons to have consistent iconography throughout the application</string>
|
||||||
|
<string name="perf_stats">Show Performance Statistics</string>
|
||||||
|
<string name="perf_stats_desc_off">Performance Statistics will not be shown</string>
|
||||||
|
<string name="perf_stats_desc_on">Performance Statistics will be shown in the top-left corner</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -43,6 +43,12 @@
|
|||||||
android:summaryOn="@string/select_action_desc_on"
|
android:summaryOn="@string/select_action_desc_on"
|
||||||
app:key="select_action"
|
app:key="select_action"
|
||||||
app:title="@string/select_action" />
|
app:title="@string/select_action" />
|
||||||
|
<CheckBoxPreference
|
||||||
|
android:defaultValue="false"
|
||||||
|
android:summaryOff="@string/perf_stats_desc_off"
|
||||||
|
android:summaryOn="@string/perf_stats_desc_on"
|
||||||
|
app:key="perf_stats"
|
||||||
|
app:title="@string/perf_stats" />
|
||||||
<ListPreference
|
<ListPreference
|
||||||
android:defaultValue="2"
|
android:defaultValue="2"
|
||||||
android:entries="@array/log_level"
|
android:entries="@array/log_level"
|
||||||
|
Loading…
Reference in New Issue
Block a user