mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-09-08 21:15:58 +00:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d1bb6445c0 | |||
| 2363ff8d34 | |||
| 50559af46d | |||
| 9002ba38c0 | |||
| c454e30249 |
Vendored
+328
-320
File diff suppressed because it is too large
Load Diff
Vendored
+317
-309
File diff suppressed because it is too large
Load Diff
Vendored
+317
-309
File diff suppressed because it is too large
Load Diff
Vendored
+317
-309
File diff suppressed because it is too large
Load Diff
Vendored
+369
-371
File diff suppressed because it is too large
Load Diff
Vendored
+317
-309
File diff suppressed because it is too large
Load Diff
Vendored
+323
-315
File diff suppressed because it is too large
Load Diff
Vendored
+322
-314
File diff suppressed because it is too large
Load Diff
Vendored
+317
-309
File diff suppressed because it is too large
Load Diff
Vendored
+317
-309
File diff suppressed because it is too large
Load Diff
Vendored
+317
-309
File diff suppressed because it is too large
Load Diff
Vendored
+317
-309
File diff suppressed because it is too large
Load Diff
Vendored
+317
-309
File diff suppressed because it is too large
Load Diff
Vendored
+335
-327
File diff suppressed because it is too large
Load Diff
Vendored
+317
-309
File diff suppressed because it is too large
Load Diff
Vendored
+317
-309
File diff suppressed because it is too large
Load Diff
Vendored
+317
-309
File diff suppressed because it is too large
Load Diff
Vendored
+317
-309
File diff suppressed because it is too large
Load Diff
Vendored
+317
-309
File diff suppressed because it is too large
Load Diff
Vendored
+317
-309
File diff suppressed because it is too large
Load Diff
Vendored
+381
-387
File diff suppressed because it is too large
Load Diff
Vendored
+317
-309
File diff suppressed because it is too large
Load Diff
Vendored
+317
-309
File diff suppressed because it is too large
Load Diff
Vendored
+317
-309
File diff suppressed because it is too large
Load Diff
Vendored
+317
-309
File diff suppressed because it is too large
Load Diff
Vendored
+317
-309
File diff suppressed because it is too large
Load Diff
Vendored
+317
-309
File diff suppressed because it is too large
Load Diff
-1
@@ -83,7 +83,6 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting {
|
|||||||
SHOW_SHADERS_BUILDING("show_shaders_building"),
|
SHOW_SHADERS_BUILDING("show_shaders_building"),
|
||||||
|
|
||||||
DEBUG_FLUSH_BY_LINE("flush_line"),
|
DEBUG_FLUSH_BY_LINE("flush_line"),
|
||||||
EXTENDED_LOGGING("extended_logging"),
|
|
||||||
DONT_SHOW_DRIVER_SHADER_WARNING("dont_show_driver_shader_warning"),
|
DONT_SHOW_DRIVER_SHADER_WARNING("dont_show_driver_shader_warning"),
|
||||||
ENABLE_OVERLAY("enable_overlay"),
|
ENABLE_OVERLAY("enable_overlay"),
|
||||||
|
|
||||||
|
|||||||
-7
@@ -262,13 +262,6 @@ abstract class SettingsItem(
|
|||||||
descriptionId = R.string.flush_by_line_description
|
descriptionId = R.string.flush_by_line_description
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
put(
|
|
||||||
SwitchSetting(
|
|
||||||
BooleanSetting.EXTENDED_LOGGING,
|
|
||||||
titleId = R.string.extended_logging,
|
|
||||||
descriptionId = R.string.extended_logging_description
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
val dockedModeSetting = object : AbstractBooleanSetting {
|
val dockedModeSetting = object : AbstractBooleanSetting {
|
||||||
override val key = BooleanSetting.USE_DOCKED_MODE.key
|
override val key = BooleanSetting.USE_DOCKED_MODE.key
|
||||||
|
|||||||
-1
@@ -1323,7 +1323,6 @@ class SettingsFragmentPresenter(
|
|||||||
add(HeaderSetting(R.string.log))
|
add(HeaderSetting(R.string.log))
|
||||||
|
|
||||||
add(BooleanSetting.DEBUG_FLUSH_BY_LINE.key)
|
add(BooleanSetting.DEBUG_FLUSH_BY_LINE.key)
|
||||||
add(BooleanSetting.EXTENDED_LOGGING.key)
|
|
||||||
add(StringSetting.LOG_FILTER.key)
|
add(StringSetting.LOG_FILTER.key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -106,7 +106,7 @@
|
|||||||
|
|
||||||
<!-- NVDEC Emulation -->
|
<!-- NVDEC Emulation -->
|
||||||
<string name="nvdec_emulation">محاكاة NVDEC</string>
|
<string name="nvdec_emulation">محاكاة NVDEC</string>
|
||||||
<string name="nvdec_emulation_description">قم بتغيير المعالج المركزي في حالة حدوث عطل أثناء المشاهد السينمائية.</string>
|
<string name="nvdec_emulation_description">حدد كيفية التعامل مع فك تشفير الفيديو (NVDEC) خلال المشاهد التمهيدية والمقدمة.</string>
|
||||||
<string name="nvdec_emulation_none">لا شيء</string>
|
<string name="nvdec_emulation_none">لا شيء</string>
|
||||||
|
|
||||||
<!-- Optimize SPIRV output -->
|
<!-- Optimize SPIRV output -->
|
||||||
@@ -292,7 +292,7 @@
|
|||||||
<string name="gpu_driver_manager">إدارة برامج تشغيل وحدة معالجة الرسومات</string>
|
<string name="gpu_driver_manager">إدارة برامج تشغيل وحدة معالجة الرسومات</string>
|
||||||
<string name="install_gpu_driver_description">تثبيت برامج تشغيل بديلة لأداء أو دقة أفضل</string>
|
<string name="install_gpu_driver_description">تثبيت برامج تشغيل بديلة لأداء أو دقة أفضل</string>
|
||||||
<string name="frame_gen">توليد الإطار</string>
|
<string name="frame_gen">توليد الإطار</string>
|
||||||
<string name="frame_gen_per_game_description">ضبط إعدادات إنشاء الإطارات لهذه اللعبة</string>
|
<string name="frame_gen_per_game_description">تكوين إعدادات إنشاء الإطارات لهذه اللعبة</string>
|
||||||
<string name="frame_gen_description">قم بإدراج الإطارات المُستكملة بين الإطارات المُعالجة باستخدام تقنية التحجيم بدون فقدان الجودة. يُفرض هذا الخيار عرض الإطارات وفقًا لترتيب FIFO عند تفعيله.</string>
|
<string name="frame_gen_description">قم بإدراج الإطارات المُستكملة بين الإطارات المُعالجة باستخدام تقنية التحجيم بدون فقدان الجودة. يُفرض هذا الخيار عرض الإطارات وفقًا لترتيب FIFO عند تفعيله.</string>
|
||||||
<string name="frame_gen_multiplier">مضاعف الإطارات</string>
|
<string name="frame_gen_multiplier">مضاعف الإطارات</string>
|
||||||
<string name="frame_gen_multiplier_description">عدد الإطارات المطلوب عرضها لكل إطار مُعالَج. تتطلب القيم الأعلى وقت معالجة رسوميات أكبر. طلب عدد إطارات يفوق قدرة الشاشة على عرضه سيؤدي إلى إبطاء المحاكاة.</string>
|
<string name="frame_gen_multiplier_description">عدد الإطارات المطلوب عرضها لكل إطار مُعالَج. تتطلب القيم الأعلى وقت معالجة رسوميات أكبر. طلب عدد إطارات يفوق قدرة الشاشة على عرضه سيؤدي إلى إبطاء المحاكاة.</string>
|
||||||
@@ -300,7 +300,6 @@
|
|||||||
<string name="frame_gen_multiplier_3x">3x</string>
|
<string name="frame_gen_multiplier_3x">3x</string>
|
||||||
<string name="frame_gen_multiplier_4x">4x</string>
|
<string name="frame_gen_multiplier_4x">4x</string>
|
||||||
<string name="frame_gen_target_rate">معدل الإطارات المستهدف</string>
|
<string name="frame_gen_target_rate">معدل الإطارات المستهدف</string>
|
||||||
<string name="frame_gen_target_rate_description">اختر المعدل الذي يمكن لشاشتك عرضه فعليًّا. عندئذٍ يرتفع المضاعف أو ينخفض تلقائيًّا للحفاظ على هذا المعدل، ويقوم بالتراجع عن أي خطوة تؤدي إلى إبطاء سير اللعبة نفسها.</string>
|
|
||||||
<string name="frame_gen_target_rate_off">استخدم مضاعفًا ثابتًا</string>
|
<string name="frame_gen_target_rate_off">استخدم مضاعفًا ثابتًا</string>
|
||||||
<string name="frame_gen_target_rate_60">60 إطارًا في الثانية</string>
|
<string name="frame_gen_target_rate_60">60 إطارًا في الثانية</string>
|
||||||
<string name="frame_gen_target_rate_90">90 إطارًا في الثانية</string>
|
<string name="frame_gen_target_rate_90">90 إطارًا في الثانية</string>
|
||||||
@@ -308,50 +307,6 @@
|
|||||||
<string name="frame_gen_target_rate_144">144 إطارًا في الثانية</string>
|
<string name="frame_gen_target_rate_144">144 إطارًا في الثانية</string>
|
||||||
<string name="frame_gen_target_rate_165">165 إطارًا في الثانية</string>
|
<string name="frame_gen_target_rate_165">165 إطارًا في الثانية</string>
|
||||||
<string name="frame_gen_queue_target">هدف قائمة انتظار الإطارات</string>
|
<string name="frame_gen_queue_target">هدف قائمة انتظار الإطارات</string>
|
||||||
<string name="frame_gen_queue_target_description">كم عدد الإطارات المكتملة التي قد تنتظر قبل عرضها؟ تعمل قوائم الانتظار الأكبر حجمًا على امتصاص الارتفاعات المفاجئة في حمل وحدة معالجة الرسومات على حساب زمن انتقال الإدخال.</string>
|
|
||||||
<string name="frame_gen_queue_target_0">أقل زمن انتقال (بدون تخزين مؤقت)</string>
|
|
||||||
<string name="frame_gen_queue_target_1">متوازن (1 إطار)</string>
|
|
||||||
<string name="frame_gen_queue_target_2">الأكثر سلاسة (2 إطارات)</string>
|
|
||||||
<string name="frame_gen_flow_scale_auto">تكييف تقدير الحركة مع اللعبة</string>
|
|
||||||
<string name="frame_gen_flow_scale_auto_description">قم بتقدير الحركة بناءً على الدقة التي تعرضها اللعبة فعليًّا، بدلاً من الإخراج الذي تم رفع دقته. ولا يؤثر ذلك على الدقة بأي شكل، لأن رفع الدقة لا يضيف أي تفاصيل تتعلق بالحركة.</string>
|
|
||||||
<string name="frame_gen_flow_scale">دقة تقدير الحركة</string>
|
|
||||||
<string name="frame_gen_flow_scale_description">دقة مسار التدفق البصري، كجزء من الناتج. ويُعد خفض هذه القيمة أرخص طريقة لاستعادة الأداء.</string>
|
|
||||||
<string name="frame_gen_fp16">مُظلِّلات نصف الدقة</string>
|
|
||||||
<string name="frame_gen_fp16_description">استخدم نسخة التظليل 16 بت. يتم التراجع تلقائيًا إلى الخيار البديل في حالة عدم توفرها في برنامج التشغيل أو الملف.</string>
|
|
||||||
<string name="frame_gen_dump_flow">إفراغ الإطار الذي تم إنشاؤه</string>
|
|
||||||
<string name="frame_gen_dump_flow_description">قم بكتابة مستويات MIP للتدفق البصري والإطار المُستكمل إلى مجلد lossless/debug مرة واحدة، لغرض استكشاف الأخطاء وإصلاحها</string>
|
|
||||||
<string name="frame_gen_unsupported">توليد الإطار غير متاح</string>
|
|
||||||
<string name="frame_gen_unsupported_description">لا يدعم برنامج تشغيل وحدة معالجة الرسومات هذا نموذج ذاكرة Vulkan، الذي تتطلبه برامج التظليل الخاصة بـ«Lossless Scaling».</string>
|
|
||||||
<string name="lossless_scaling_setup_description">اختياري. قم بتوفير ملف Lossless.dll الخاص بك لتمكين إنشاء الإطارات لاحقًا</string>
|
|
||||||
<string name="lossless_scaling_install">تثبيت ملف Lossless.dll</string>
|
|
||||||
<string name="lossless_scaling_install_description">يتطلب إنشاء الإطارات أن تكون لديك نسخة قانونية خاصة بك من ملف Lossless.dll المأخوذ من برنامج Lossless Scaling</string>
|
|
||||||
<string name="lossless_scaling_replace_description">اختر نسخة أخرى من ملف Lossless.dll</string>
|
|
||||||
<string name="frame_generation_support">توليد الإطارات</string>
|
|
||||||
<string name="frame_generation_supported">مدعوم</string>
|
|
||||||
<string name="frame_generation_unsupported">غير مدعوم (لا يتوفر نموذج ذاكرة Vulkan)</string>
|
|
||||||
<string name="lossless_scaling">Lossless Scaling</string>
|
|
||||||
<string name="lossless_scaling_description">قم بتوفير نسختك الخاصة من ملف Lossless.dll لتمكين توليد الإطارات</string>
|
|
||||||
<string name="lossless_scaling_installed">مثبت</string>
|
|
||||||
<string name="lossless_scaling_not_installed">غير مثبت</string>
|
|
||||||
<string name="lossless_scaling_replace">استبدل</string>
|
|
||||||
<string name="lossless_scaling_remove">إزالة</string>
|
|
||||||
<string name="lossless_scaling_remove_description">احذف ملف Lossless.dll المثبت ووحدات التظليل المعدة له</string>
|
|
||||||
<string name="lossless_scaling_remove_confirmation">سيتوقف توليد الإطارات عن العمل إلى أن تقوم بتثبيت ملف Lossless.dll مرة أخرى. ولن يتأثر ملفك الأصلي بذلك.</string>
|
|
||||||
<string name="lossless_scaling_missing">ملف Lossless.dll غير مثبت</string>
|
|
||||||
<string name="lossless_scaling_missing_description">قم بتثبيته من الإعدادات › Lossless Scaling لاستخدام ميزة توليد الإطارات.</string>
|
|
||||||
<string name="lossless_scaling_locked">أغلق اللعبة أولاً</string>
|
|
||||||
<string name="lossless_scaling_locked_description">لا يمكن تعديل ملف Lossless.dll أثناء تشغيل اللعبة.</string>
|
|
||||||
<string name="lossless_scaling_remove_unavailable">لا يوجد شيء يجب إزالته</string>
|
|
||||||
<string name="lossless_scaling_remove_unavailable_description">لم يتم تثبيت ملف Lossless.dll بعد.</string>
|
|
||||||
<string name="lossless_scaling_installing">جاري التحضير لإنشاء مظلّلات الإطارات…</string>
|
|
||||||
<string name="lossless_scaling_install_success">تم تثبيت ملف Lossless.dll بنجاح</string>
|
|
||||||
<string name="lossless_scaling_install_failed">تعذر تثبيت ملف Lossless.dll</string>
|
|
||||||
<string name="error_lossless_copy_failed">تعذر نسخ الملف المحدد.</string>
|
|
||||||
<string name="error_lossless_unreadable">تعذر قراءة الملف المحدد.</string>
|
|
||||||
<string name="error_lossless_not_pe">الملف المحدد ليس مكتبة Windows. حدد ملف Lossless.dll من تثبيت برنامج Lossless Scaling.</string>
|
|
||||||
<string name="error_lossless_missing_shaders">لا تحتوي هذه النسخة من ملف Lossless.dll على برامج التظليل الخاصة بتوليد الإطارات. قم بتحديث ميزة «Lossless Scaling» وحاول مرة أخرى.</string>
|
|
||||||
<string name="error_lossless_translation_failed">تعذر ترجمة برامج التظليل الخاصة بتوليد الإطارات. هذا الإصدار من «Lossless Scaling» غير مدعوم حتى الآن.</string>
|
|
||||||
<string name="error_lossless_cache_failed">تعذر كتابة برامج التظليل المترجمة إلى وحدة التخزين. تأكد من توفر مساحة خالية.</string>
|
|
||||||
<string name="advanced_settings">الإعدادات المتقدمة</string>
|
<string name="advanced_settings">الإعدادات المتقدمة</string>
|
||||||
<string name="settings_description">ضبط إعدادات المحاكي</string>
|
<string name="settings_description">ضبط إعدادات المحاكي</string>
|
||||||
<string name="search_recently_played">تم تشغيلها مؤخرًا</string>
|
<string name="search_recently_played">تم تشغيلها مؤخرًا</string>
|
||||||
@@ -630,10 +585,6 @@
|
|||||||
<string name="log">السجلات</string>
|
<string name="log">السجلات</string>
|
||||||
<string name="flush_by_line">تفريغ سجلات التصحيح حسب السطر</string>
|
<string name="flush_by_line">تفريغ سجلات التصحيح حسب السطر</string>
|
||||||
<string name="flush_by_line_description">يفرغ سجلات التصحيح عند كتابة كل سطر، مما يجعل التصحيح أسهل في حالات التوقف أو التجميد.</string>
|
<string name="flush_by_line_description">يفرغ سجلات التصحيح عند كتابة كل سطر، مما يجعل التصحيح أسهل في حالات التوقف أو التجميد.</string>
|
||||||
<string name="extended_logging">تفعيل التسجيل الموسع</string>
|
|
||||||
<string name="extended_logging_description">يزيد الحد الأقصى لحجم ملف السجل من 100 ميجابايت إلى 1 جيجابايت.</string>
|
|
||||||
<string name="log_filter">مرشح السجلات</string>
|
|
||||||
<string name="log_filter_description">يتحكم في فئات سجلات Eden. مثال: *:Info Service.LM:Debug</string>
|
|
||||||
|
|
||||||
<!-- GPU Logging strings -->
|
<!-- GPU Logging strings -->
|
||||||
<string name="gpu_logging_header">تسجيل وحدة معالجة الرسومات</string>
|
<string name="gpu_logging_header">تسجيل وحدة معالجة الرسومات</string>
|
||||||
@@ -710,10 +661,10 @@
|
|||||||
<string name="gamecube_controller">ذراع تحكم GameCube</string>
|
<string name="gamecube_controller">ذراع تحكم GameCube</string>
|
||||||
<string name="invert_axis">عكس المحور</string>
|
<string name="invert_axis">عكس المحور</string>
|
||||||
<string name="invert_button">عكس الزر</string>
|
<string name="invert_button">عكس الزر</string>
|
||||||
<string name="toggle_button">زر تفعيل/تعطيل</string>
|
<string name="toggle_button">زر تشغيل/إيقاف</string>
|
||||||
<string name="turbo_button">زر التوربو</string>
|
<string name="turbo_button">زر التوربو</string>
|
||||||
<string name="set_threshold">تعيين الحد الفاصل</string>
|
<string name="set_threshold">تعيين الحد الفاصل</string>
|
||||||
<string name="toggle_axis">تفعيل/تعطيل المحور</string>
|
<string name="toggle_axis">تشغيل/إيقاف المحور</string>
|
||||||
<string name="connected">متصل</string>
|
<string name="connected">متصل</string>
|
||||||
<string name="use_system_vibrator">استخدم هزاز النظام</string>
|
<string name="use_system_vibrator">استخدم هزاز النظام</string>
|
||||||
<string name="input_overlay">طبقة الإدخال</string>
|
<string name="input_overlay">طبقة الإدخال</string>
|
||||||
@@ -852,7 +803,7 @@
|
|||||||
<string name="version">الإصدار</string>
|
<string name="version">الإصدار</string>
|
||||||
<string name="copy_details">نسخ التفاصيل</string>
|
<string name="copy_details">نسخ التفاصيل</string>
|
||||||
<string name="add_ons">الإضافات</string>
|
<string name="add_ons">الإضافات</string>
|
||||||
<string name="add_ons_description">تفعيل/تعطيل التعديلات، التحديثات، المحتوى القابل للتنزيل</string>
|
<string name="add_ons_description">التعديلات، التحديثات، المحتوى القابل للتنزيل</string>
|
||||||
<string name="playtime">زمن اللعب:</string>
|
<string name="playtime">زمن اللعب:</string>
|
||||||
<string name="reset_playtime">مسح زمن اللعب</string>
|
<string name="reset_playtime">مسح زمن اللعب</string>
|
||||||
<string name="reset_playtime_description">إعادة تعيين زمن اللعب للعبة الحالية إلى 0 ثانية</string>
|
<string name="reset_playtime_description">إعادة تعيين زمن اللعب للعبة الحالية إلى 0 ثانية</string>
|
||||||
@@ -957,13 +908,13 @@
|
|||||||
<!-- Emulation Menu -->
|
<!-- Emulation Menu -->
|
||||||
<string name="emulation_exit">خروج من المحاكاة</string>
|
<string name="emulation_exit">خروج من المحاكاة</string>
|
||||||
<string name="emulation_done">إنهاء</string>
|
<string name="emulation_done">إنهاء</string>
|
||||||
<string name="emulation_toggle_controls">تفعيل/تعطيل أزرار التحكم</string>
|
<string name="emulation_toggle_controls">تشغيل/إيقاف أزرار التحكم</string>
|
||||||
<string name="emulation_rel_stick_center">مركز العصا النسبي</string>
|
<string name="emulation_rel_stick_center">مركز العصا النسبي</string>
|
||||||
<string name="emulation_dpad_slide">انزلاق الأسهم</string>
|
<string name="emulation_dpad_slide">انزلاق الأسهم</string>
|
||||||
<string name="emulation_haptics">الاهتزازات الديناميكية</string>
|
<string name="emulation_haptics">الاهتزازات الديناميكية</string>
|
||||||
<string name="emulation_show_overlay">عرض ذراع التحكم</string>
|
<string name="emulation_show_overlay">عرض ذراع التحكم</string>
|
||||||
<string name="emulation_hide_overlay">إخفاء ذراع التحكم</string>
|
<string name="emulation_hide_overlay">إخفاء ذراع التحكم</string>
|
||||||
<string name="emulation_toggle_all">تفعيل/تعطيل الكل</string>
|
<string name="emulation_toggle_all">تشغيل/إيقاف الكل</string>
|
||||||
<string name="emulation_control_adjust">ضبط الطبقة</string>
|
<string name="emulation_control_adjust">ضبط الطبقة</string>
|
||||||
<string name="emulation_control_scale">الحجم</string>
|
<string name="emulation_control_scale">الحجم</string>
|
||||||
<string name="emulation_control_opacity">الشفافية</string>
|
<string name="emulation_control_opacity">الشفافية</string>
|
||||||
@@ -1128,7 +1079,7 @@
|
|||||||
<string name="freedreno_info_title">حول إعدادات Freedreno</string>
|
<string name="freedreno_info_title">حول إعدادات Freedreno</string>
|
||||||
<string name="freedreno_info_description">قم بإعداد خيارات برنامج تشغيل Freedreno/Turnip لوحدة معالجة الرسومات لأغراض التصحيح، والتحليل، وتحسين الأداء. يتم حفظ التغييرات تلقائيًا. راجع https://docs.mesa3d.org/drivers/freedreno.html للحصول على الوثائق التفصيلية.</string>
|
<string name="freedreno_info_description">قم بإعداد خيارات برنامج تشغيل Freedreno/Turnip لوحدة معالجة الرسومات لأغراض التصحيح، والتحليل، وتحسين الأداء. يتم حفظ التغييرات تلقائيًا. راجع https://docs.mesa3d.org/drivers/freedreno.html للحصول على الوثائق التفصيلية.</string>
|
||||||
<string name="freedreno_per_game_title">إعدادات Freedreno</string>
|
<string name="freedreno_per_game_title">إعدادات Freedreno</string>
|
||||||
<string name="freedreno_per_game_description">ضبط إعدادات برنامج تشغيل وحدة معالجة الرسومات لهذه اللعبة</string>
|
<string name="freedreno_per_game_description">قم بضبط إعدادات برنامج تشغيل وحدة معالجة الرسومات لهذه اللعبة</string>
|
||||||
<string name="freedreno_per_game_saved">تم حفظ إعدادات Freedreno</string>
|
<string name="freedreno_per_game_saved">تم حفظ إعدادات Freedreno</string>
|
||||||
|
|
||||||
<!-- Gamepad Buttons -->
|
<!-- Gamepad Buttons -->
|
||||||
@@ -1156,6 +1107,7 @@
|
|||||||
<string name="theme_mode_light">فاتح</string>
|
<string name="theme_mode_light">فاتح</string>
|
||||||
<string name="theme_mode_dark">داكن</string>
|
<string name="theme_mode_dark">داكن</string>
|
||||||
|
|
||||||
|
|
||||||
<!-- Black backgrounds theme -->
|
<!-- Black backgrounds theme -->
|
||||||
<string name="use_black_backgrounds">خلفيات سوداء</string>
|
<string name="use_black_backgrounds">خلفيات سوداء</string>
|
||||||
<string name="use_black_backgrounds_description">عند استخدام السمة الداكنة، قم بتطبيق خلفيات سوداء.</string>
|
<string name="use_black_backgrounds_description">عند استخدام السمة الداكنة، قم بتطبيق خلفيات سوداء.</string>
|
||||||
|
|||||||
@@ -62,6 +62,7 @@
|
|||||||
<string name="cpuopt_unsafe_host_mmu_description">ئەم باشکردنە خێرایی دەستکەوتنی بیرگە لەلایەن پرۆگرامی میوانەکە زیاد دەکات. چالاککردنی وای لێدەکات کە خوێندنەوە/نووسینەکانی بیرگەی میوانەکە ڕاستەوخۆ لە بیرگە ئەنجام بدرێت و میمیکردنی MMU میواندە بەکاربهێنێت. ناچالاککردنی ئەمە هەموو دەستکەوتنەکانی بیرگە ڕەت دەکاتەوە لە بەکارهێنانی میمیکردنی MMU نەرمەکاڵا.</string>
|
<string name="cpuopt_unsafe_host_mmu_description">ئەم باشکردنە خێرایی دەستکەوتنی بیرگە لەلایەن پرۆگرامی میوانەکە زیاد دەکات. چالاککردنی وای لێدەکات کە خوێندنەوە/نووسینەکانی بیرگەی میوانەکە ڕاستەوخۆ لە بیرگە ئەنجام بدرێت و میمیکردنی MMU میواندە بەکاربهێنێت. ناچالاککردنی ئەمە هەموو دەستکەوتنەکانی بیرگە ڕەت دەکاتەوە لە بەکارهێنانی میمیکردنی MMU نەرمەکاڵا.</string>
|
||||||
<!-- NVDEC Emulation -->
|
<!-- NVDEC Emulation -->
|
||||||
<string name="nvdec_emulation">ئیمولەیشنی NVDEC</string>
|
<string name="nvdec_emulation">ئیمولەیشنی NVDEC</string>
|
||||||
|
<string name="nvdec_emulation_description">هەڵبژاردنی ڕێگای دیکۆدکردنی ڤیدیۆ</string>
|
||||||
<string name="nvdec_emulation_none">هیچ</string>
|
<string name="nvdec_emulation_none">هیچ</string>
|
||||||
|
|
||||||
<!-- Optimize SPIRV output -->
|
<!-- Optimize SPIRV output -->
|
||||||
@@ -378,6 +379,7 @@
|
|||||||
<string name="log">تۆمارکردن</string>
|
<string name="log">تۆمارکردن</string>
|
||||||
<string name="flush_by_line">خاوکردنەوەی تۆمارەکانی دیباگ بە هێڵ</string>
|
<string name="flush_by_line">خاوکردنەوەی تۆمارەکانی دیباگ بە هێڵ</string>
|
||||||
<string name="flush_by_line_description">تۆمارەکانی دیباگ لە هەر هێڵێکدا دەنوسرێت خاو دەکاتەوە، ئەمە وا دەکات دیباگکردن ئاسانتر بێت لە کاتی کرشکردن یان پێکەنین.</string>
|
<string name="flush_by_line_description">تۆمارەکانی دیباگ لە هەر هێڵێکدا دەنوسرێت خاو دەکاتەوە، ئەمە وا دەکات دیباگکردن ئاسانتر بێت لە کاتی کرشکردن یان پێکەنین.</string>
|
||||||
|
|
||||||
<!-- Audio settings strings -->
|
<!-- Audio settings strings -->
|
||||||
<string name="audio_output_engine">بزوێنری دەرچوونی دەنگ</string>
|
<string name="audio_output_engine">بزوێنری دەرچوونی دەنگ</string>
|
||||||
<string name="audio_volume">دەنگ</string>
|
<string name="audio_volume">دەنگ</string>
|
||||||
|
|||||||
@@ -97,6 +97,7 @@
|
|||||||
|
|
||||||
<!-- NVDEC Emulation -->
|
<!-- NVDEC Emulation -->
|
||||||
<string name="nvdec_emulation">Emulace NVDEC</string>
|
<string name="nvdec_emulation">Emulace NVDEC</string>
|
||||||
|
<string name="nvdec_emulation_description">Určuje, jakým způsobem se zpracovává dekódování videa (NVDEC).</string>
|
||||||
<string name="nvdec_emulation_none">Žádné</string>
|
<string name="nvdec_emulation_none">Žádné</string>
|
||||||
|
|
||||||
<!-- Optimize SPIRV output -->
|
<!-- Optimize SPIRV output -->
|
||||||
@@ -495,6 +496,7 @@
|
|||||||
<string name="log">Protokolování</string>
|
<string name="log">Protokolování</string>
|
||||||
<string name="flush_by_line">Vypisovat ladicí záznamy po řádcích</string>
|
<string name="flush_by_line">Vypisovat ladicí záznamy po řádcích</string>
|
||||||
<string name="flush_by_line_description">Vypisuje ladicí záznamy po každém napsaném řádku, což usnadňuje ladění v případě pádu nebo zamrznutí.</string>
|
<string name="flush_by_line_description">Vypisuje ladicí záznamy po každém napsaném řádku, což usnadňuje ladění v případě pádu nebo zamrznutí.</string>
|
||||||
|
|
||||||
<!-- Audio settings strings -->
|
<!-- Audio settings strings -->
|
||||||
<string name="audio_output_engine">Výstupní engine</string>
|
<string name="audio_output_engine">Výstupní engine</string>
|
||||||
<string name="audio_volume">Hlasitost</string>
|
<string name="audio_volume">Hlasitost</string>
|
||||||
|
|||||||
@@ -64,8 +64,8 @@
|
|||||||
<string name="bat_temperature_unit">Batterietemperatur-Einheiten</string>
|
<string name="bat_temperature_unit">Batterietemperatur-Einheiten</string>
|
||||||
<string name="show_power_info">Batterieinfo anzeigen</string>
|
<string name="show_power_info">Batterieinfo anzeigen</string>
|
||||||
<string name="show_power_info_description">Aktuellen Stromverbrauch und verbleibende Kapazität der Batterie anzeigen</string>
|
<string name="show_power_info_description">Aktuellen Stromverbrauch und verbleibende Kapazität der Batterie anzeigen</string>
|
||||||
<string name="show_shaders_building">Shader-Erstellung anzeigen</string>
|
<string name="show_shaders_building">Schattierer-Erstellung anzeigen</string>
|
||||||
<string name="show_shaders_building_description">Aktuelle Anzahl der erstellten Shader anzeigen</string>
|
<string name="show_shaders_building_description">Aktuelle Anzahl der erstellten Schattierer anzeigen</string>
|
||||||
<string name="pipeline_worker_cores_description">Lege die Anzahl der Kerne fest, die für die Erstellung von Vulkan-Rohrleitungen verwendet werden sollen. Ein höherer Wert verbessert die Kompilierungsleistung der Rohrleitung, führt jedoch auch zu einem Anstieg der Temperaturen.</string>
|
<string name="pipeline_worker_cores_description">Lege die Anzahl der Kerne fest, die für die Erstellung von Vulkan-Rohrleitungen verwendet werden sollen. Ein höherer Wert verbessert die Kompilierungsleistung der Rohrleitung, führt jedoch auch zu einem Anstieg der Temperaturen.</string>
|
||||||
<string name="overlay_position">Überlagerungs-Position</string>
|
<string name="overlay_position">Überlagerungs-Position</string>
|
||||||
<string name="overlay_position_description">Wähle aus, wo die Überlagerung auf dem Bildschirm angezeigt wird</string>
|
<string name="overlay_position_description">Wähle aus, wo die Überlagerung auf dem Bildschirm angezeigt wird</string>
|
||||||
@@ -105,7 +105,7 @@
|
|||||||
|
|
||||||
<!-- NVDEC Emulation -->
|
<!-- NVDEC Emulation -->
|
||||||
<string name="nvdec_emulation">NVDEC-Emulation</string>
|
<string name="nvdec_emulation">NVDEC-Emulation</string>
|
||||||
<string name="nvdec_emulation_description">Wechsle auf CPU, falls ein Absturz bei einem Cinematic auftritt.</string>
|
<string name="nvdec_emulation_description">Wähle aus, wie die Videodekodierung (NVDEC) während Zwischensequenzen und Intros gehandhabt wird.</string>
|
||||||
<string name="nvdec_emulation_none">Keine</string>
|
<string name="nvdec_emulation_none">Keine</string>
|
||||||
|
|
||||||
<!-- Optimize SPIRV output -->
|
<!-- Optimize SPIRV output -->
|
||||||
@@ -290,38 +290,6 @@
|
|||||||
<string name="gpu_driver_fetcher">GPU-Treiber-Hersteller</string>
|
<string name="gpu_driver_fetcher">GPU-Treiber-Hersteller</string>
|
||||||
<string name="gpu_driver_manager">GPU-Treiber Verwaltung</string>
|
<string name="gpu_driver_manager">GPU-Treiber Verwaltung</string>
|
||||||
<string name="install_gpu_driver_description">Alternative Treiber für eventuell bessere Leistung oder Genauigkeit installieren</string>
|
<string name="install_gpu_driver_description">Alternative Treiber für eventuell bessere Leistung oder Genauigkeit installieren</string>
|
||||||
<string name="frame_gen">Frame-Generation</string>
|
|
||||||
<string name="frame_gen_per_game_description">Konfiguriere Frame-Generation für dieses Spiel</string>
|
|
||||||
<string name="frame_gen_description">Füge zwischen den gerenderten Bildern interpolierte Bilder mithilfe von Lossless Scaling ein. </string>
|
|
||||||
<string name="frame_gen_multiplier">Frame-Multiplikator</string>
|
|
||||||
<string name="frame_gen_multiplier_description">Wie viele Bilder für jedes gerenderte angezeigt werden soll. Höhere Werte kosten proportional mehr GPU-Zeit. Nach mehr zu fragen, als dein Bildschirm darstellen kann, wird die Emulation verlangsamen.</string>
|
|
||||||
<string name="frame_gen_multiplier_2x">2x</string>
|
|
||||||
<string name="frame_gen_multiplier_3x">3x</string>
|
|
||||||
<string name="frame_gen_multiplier_4x">4x</string>
|
|
||||||
<string name="frame_gen_target_rate">Ziel-Bildrate</string>
|
|
||||||
<string name="frame_gen_target_rate_description">Wähle die Rate aus die dein Bildschirm tatsächlich darstellen kann. Der Multiplikator steigt oder fällt dann alleine um sie zu halten, und rollt jeden Schritt zurück, der das Spiel selber langsamer macht.</string>
|
|
||||||
<string name="frame_gen_target_rate_off">Nutze einen fixierten Multiplikator</string>
|
|
||||||
<string name="frame_gen_target_rate_60">60 FPS</string>
|
|
||||||
<string name="frame_gen_target_rate_90">90 FPS</string>
|
|
||||||
<string name="frame_gen_target_rate_120">120 FPS</string>
|
|
||||||
<string name="frame_gen_target_rate_144">144 FPS</string>
|
|
||||||
<string name="frame_gen_target_rate_165">165 FPS</string>
|
|
||||||
<string name="frame_gen_queue_target_1">Ausbalanciert (1 Bild)</string>
|
|
||||||
<string name="frame_gen_queue_target_2">Flüssigste (2 Bilder)</string>
|
|
||||||
<string name="frame_gen_unsupported">Frame-Generation nicht verfügbar</string>
|
|
||||||
<string name="frame_gen_unsupported_description">Dieser GPU-Treiber unterstützt das Vulkan-Memory-Model nicht, welches Lossless Scaling-Shader benötigen.</string>
|
|
||||||
<string name="lossless_scaling_setup_description">Optional. Stelle deine eigene Lossless.dll zur Verfügung, um Frame-Generation später zu aktivieren.</string>
|
|
||||||
<string name="lossless_scaling_install">Installiere Lossless.dll</string>
|
|
||||||
<string name="lossless_scaling_replace_description">Wähle eine andere Kopie von Lossless.dll</string>
|
|
||||||
<string name="frame_generation_supported">Unterstützt</string>
|
|
||||||
<string name="frame_generation_unsupported">Nicht unterstützt (kein Vulkan-Memory-Model)</string>
|
|
||||||
<string name="lossless_scaling">Lossless Scaling</string>
|
|
||||||
<string name="lossless_scaling_installed">Installiert</string>
|
|
||||||
<string name="lossless_scaling_not_installed">Nicht installiert</string>
|
|
||||||
<string name="lossless_scaling_replace">Ersetzen</string>
|
|
||||||
<string name="lossless_scaling_remove">Entfernen</string>
|
|
||||||
<string name="lossless_scaling_locked">Schließe zuerst das Spiel</string>
|
|
||||||
<string name="lossless_scaling_remove_unavailable">Nichts zum Entfernen</string>
|
|
||||||
<string name="advanced_settings">Erweiterte Einstellungen</string>
|
<string name="advanced_settings">Erweiterte Einstellungen</string>
|
||||||
<string name="settings_description">Emulatoreinstellungen konfigurieren</string>
|
<string name="settings_description">Emulatoreinstellungen konfigurieren</string>
|
||||||
<string name="search_recently_played">Kürzlich gespielt</string>
|
<string name="search_recently_played">Kürzlich gespielt</string>
|
||||||
@@ -426,7 +394,6 @@ Wirklich fortfahren?</string>
|
|||||||
<string name="copied_to_clipboard">In die Zwischenablage kopiert</string>
|
<string name="copied_to_clipboard">In die Zwischenablage kopiert</string>
|
||||||
<string name="about_app_description">Ein quelloffener Switch-Emulator</string>
|
<string name="about_app_description">Ein quelloffener Switch-Emulator</string>
|
||||||
<string name="contributors">Beitragende</string>
|
<string name="contributors">Beitragende</string>
|
||||||
<string name="contributors_description">Personen, die Eden für Android möglich gemacht haben</string>
|
|
||||||
<string name="licenses_description">Projekte, die Eden für Android möglich machen </string>
|
<string name="licenses_description">Projekte, die Eden für Android möglich machen </string>
|
||||||
<string name="build">Build</string>
|
<string name="build">Build</string>
|
||||||
<string name="user_data">Nutzerdaten</string>
|
<string name="user_data">Nutzerdaten</string>
|
||||||
@@ -462,8 +429,6 @@ Wird der Handheld-Modus verwendet, verringert es die Auflösung und erhöht die
|
|||||||
<string name="use_custom_rtc_description">Ermöglicht Ihnen, eine benutzerdefinierte Echtzeituhr unabhängig von Ihrer aktuellen Systemzeit einzustellen.</string>
|
<string name="use_custom_rtc_description">Ermöglicht Ihnen, eine benutzerdefinierte Echtzeituhr unabhängig von Ihrer aktuellen Systemzeit einzustellen.</string>
|
||||||
<string name="set_custom_rtc">Legen Sie eine benutzerdefinierte Echtzeituhr fest</string>
|
<string name="set_custom_rtc">Legen Sie eine benutzerdefinierte Echtzeituhr fest</string>
|
||||||
|
|
||||||
<!-- CPU -->
|
|
||||||
<string name="fast_cpu_time">CPU-Takte</string>
|
|
||||||
<string name="custom_cpu_ticks">Benutzerdefinierte CPU-Ticks</string>
|
<string name="custom_cpu_ticks">Benutzerdefinierte CPU-Ticks</string>
|
||||||
<string name="custom_cpu_ticks_description">Legen Sie einen benutzerdefinierten Wert für CPU-Ticks fest. Höhere Werte können die Leistung steigern, aber auch zum Einfrieren des Spiels führen. Ein Bereich von 77–21000 wird empfohlen.</string>
|
<string name="custom_cpu_ticks_description">Legen Sie einen benutzerdefinierten Wert für CPU-Ticks fest. Höhere Werte können die Leistung steigern, aber auch zum Einfrieren des Spiels führen. Ein Bereich von 77–21000 wird empfohlen.</string>
|
||||||
<string name="cpu_ticks">Ticks</string>
|
<string name="cpu_ticks">Ticks</string>
|
||||||
@@ -508,14 +473,10 @@ Wird der Handheld-Modus verwendet, verringert es die Auflösung und erhöht die
|
|||||||
<string name="renderer_reactive_flushing_description">Verbessert die Genauigkeit in einigen Spielen.</string>
|
<string name="renderer_reactive_flushing_description">Verbessert die Genauigkeit in einigen Spielen.</string>
|
||||||
<string name="hacks">Hacks</string>
|
<string name="hacks">Hacks</string>
|
||||||
|
|
||||||
<string name="fast_gpu_time">GPU-Takte</string>
|
|
||||||
<string name="skip_cpu_inner_invalidation">CPU-interne Invalidierung überspringen</string>
|
<string name="skip_cpu_inner_invalidation">CPU-interne Invalidierung überspringen</string>
|
||||||
<string name="skip_cpu_inner_invalidation_description">Überspringt bestimmte Cache-Invalidierungen auf CPU-Seite während Speicherupdates, reduziert die CPU-Auslastung und verbessert die Leistung. Kann in einigen Spielen zu Fehlern oder Abstürzen führen.</string>
|
<string name="skip_cpu_inner_invalidation_description">Überspringt bestimmte Cache-Invalidierungen auf CPU-Seite während Speicherupdates, reduziert die CPU-Auslastung und verbessert die Leistung. Kann in einigen Spielen zu Fehlern oder Abstürzen führen.</string>
|
||||||
<string name="renderer_asynchronous_shaders">Asynchrone Shader</string>
|
<string name="renderer_asynchronous_shaders">Asynchrone Shader</string>
|
||||||
<string name="renderer_asynchronous_shaders_description">Kompiliert Shader asynchron. Dies kann Ruckler reduzieren, aber auch Grafikfehler verursachen.</string>
|
<string name="renderer_asynchronous_shaders_description">Kompiliert Shader asynchron. Dies kann Ruckler reduzieren, aber auch Grafikfehler verursachen.</string>
|
||||||
<string name="gpu_unswizzle_default_button">Standard</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="extensions">Erweiterungen</string>
|
<string name="extensions">Erweiterungen</string>
|
||||||
|
|
||||||
<string name="dyna_state">Erweiterter dynamischer Status</string>
|
<string name="dyna_state">Erweiterter dynamischer Status</string>
|
||||||
@@ -537,7 +498,6 @@ Wird der Handheld-Modus verwendet, verringert es die Auflösung und erhöht die
|
|||||||
|
|
||||||
<!-- Debug settings strings -->
|
<!-- Debug settings strings -->
|
||||||
<string name="cpu">CPU</string>
|
<string name="cpu">CPU</string>
|
||||||
<string name="clocks">Takte</string>
|
|
||||||
<string name="use_auto_stub">Auto-Stub verwenden</string>
|
<string name="use_auto_stub">Auto-Stub verwenden</string>
|
||||||
<string name="use_auto_stub_description">Ergänzt automatisch fehlende Dienste und Funktionen. Kann die Kompatibilität verbessern, aber auch zu Abstürzen und Stabilitätsproblemen führen.</string>
|
<string name="use_auto_stub_description">Ergänzt automatisch fehlende Dienste und Funktionen. Kann die Kompatibilität verbessern, aber auch zu Abstürzen und Stabilitätsproblemen führen.</string>
|
||||||
|
|
||||||
@@ -552,6 +512,7 @@ Wird der Handheld-Modus verwendet, verringert es die Auflösung und erhöht die
|
|||||||
<string name="log">Protokollierung</string>
|
<string name="log">Protokollierung</string>
|
||||||
<string name="flush_by_line">Debug-Protokolle zeilenweise leeren</string>
|
<string name="flush_by_line">Debug-Protokolle zeilenweise leeren</string>
|
||||||
<string name="flush_by_line_description">Leert Debug-Protokolle bei jeder geschriebenen Zeile, was das Debuggen bei Abstürzen oder Einfrieren erleichtert.</string>
|
<string name="flush_by_line_description">Leert Debug-Protokolle bei jeder geschriebenen Zeile, was das Debuggen bei Abstürzen oder Einfrieren erleichtert.</string>
|
||||||
|
|
||||||
<string name="general">Allgemein</string>
|
<string name="general">Allgemein</string>
|
||||||
|
|
||||||
<!-- Audio settings strings -->
|
<!-- Audio settings strings -->
|
||||||
@@ -792,7 +753,6 @@ Wirklich fortfahren?</string>
|
|||||||
<string name="confirm_uninstall">Bestätigen Sie die Deinstallation</string>
|
<string name="confirm_uninstall">Bestätigen Sie die Deinstallation</string>
|
||||||
<string name="confirm_uninstall_description">Möchten Sie dieses Add-on wirklich deinstallieren\?</string>
|
<string name="confirm_uninstall_description">Möchten Sie dieses Add-on wirklich deinstallieren\?</string>
|
||||||
<string name="verify_integrity">Integrität prüfen</string>
|
<string name="verify_integrity">Integrität prüfen</string>
|
||||||
<string name="verifying">Verifiziere...</string>
|
|
||||||
<string name="verify_success">Integritätsüberprüfung erfolgreich!</string>
|
<string name="verify_success">Integritätsüberprüfung erfolgreich!</string>
|
||||||
<string name="verify_failure">Integritätsüberprüfung fehlgeschlagen!</string>
|
<string name="verify_failure">Integritätsüberprüfung fehlgeschlagen!</string>
|
||||||
<string name="verify_failure_description">Der Dateiinhalt ist möglicherweise beschädigt</string>
|
<string name="verify_failure_description">Der Dateiinhalt ist möglicherweise beschädigt</string>
|
||||||
@@ -914,16 +874,6 @@ Wirklich fortfahren?</string>
|
|||||||
<string name="memory_6gb">6 GB (Unsicher)</string>
|
<string name="memory_6gb">6 GB (Unsicher)</string>
|
||||||
<string name="memory_8gb">8 GB (Unsicher)</string>
|
<string name="memory_8gb">8 GB (Unsicher)</string>
|
||||||
|
|
||||||
<!-- CPU clock levels -->
|
|
||||||
<string name="clock_normal">Normal</string>
|
|
||||||
<string name="clock_boost">Beschleunigung</string>
|
|
||||||
<string name="clock_fast">Übertaktung</string>
|
|
||||||
|
|
||||||
<!-- GPU clock levels -->
|
|
||||||
<string name="fast_gpu_normal">Normal</string>
|
|
||||||
<string name="fast_gpu_medium">Beschleunigung</string>
|
|
||||||
<string name="fast_gpu_high">Übertaktung</string>
|
|
||||||
|
|
||||||
<!-- GPU swizzle texture size -->
|
<!-- GPU swizzle texture size -->
|
||||||
<string name="gpu_texturesizeswizzle_verysmall">Sehr klein (16 MB)</string>
|
<string name="gpu_texturesizeswizzle_verysmall">Sehr klein (16 MB)</string>
|
||||||
<string name="gpu_texturesizeswizzle_small">Klein (32 MB)</string>
|
<string name="gpu_texturesizeswizzle_small">Klein (32 MB)</string>
|
||||||
@@ -969,13 +919,6 @@ Wirklich fortfahren?</string>
|
|||||||
<string name="dma_accuracy_unsafe">Unsicher</string>
|
<string name="dma_accuracy_unsafe">Unsicher</string>
|
||||||
<string name="dma_accuracy_safe">Sicher</string>
|
<string name="dma_accuracy_safe">Sicher</string>
|
||||||
|
|
||||||
<!-- GPU Fence Behavior -->
|
|
||||||
<string name="gpu_fence_behavior_default">Standard</string>
|
|
||||||
<string name="gpu_fence_behavior_immediate">Direkt</string>
|
|
||||||
<string name="gpu_fence_behavior_balanced">Ausgewogen</string>
|
|
||||||
<string name="gpu_fence_behavior_accurate">Genau</string>
|
|
||||||
<string name="gpu_fence_behavior_strict">Strikt</string>
|
|
||||||
|
|
||||||
<string name="vram_usage_conservative">Konservativ</string>
|
<string name="vram_usage_conservative">Konservativ</string>
|
||||||
<string name="vram_usage_aggressive">Aggressiv</string>
|
<string name="vram_usage_aggressive">Aggressiv</string>
|
||||||
|
|
||||||
@@ -1042,32 +985,27 @@ Wirklich fortfahren?</string>
|
|||||||
<string name="theme_material_you">Material You</string>
|
<string name="theme_material_you">Material You</string>
|
||||||
<string name="app_settings">App-Einstellungen</string>
|
<string name="app_settings">App-Einstellungen</string>
|
||||||
<string name="theme_and_color">Theme und Farben</string>
|
<string name="theme_and_color">Theme und Farben</string>
|
||||||
<string name="fullscreen_mode">Vollbild-Modus</string>
|
|
||||||
<!-- Theme Modes -->
|
<!-- Theme Modes -->
|
||||||
<string name="change_theme_mode">Design</string>
|
<string name="change_theme_mode">Design</string>
|
||||||
<string name="theme_mode_follow_system">System folgen</string>
|
<string name="theme_mode_follow_system">System folgen</string>
|
||||||
<string name="theme_mode_light">Hell</string>
|
<string name="theme_mode_light">Hell</string>
|
||||||
<string name="theme_mode_dark">Dunkel</string>
|
<string name="theme_mode_dark">Dunkel</string>
|
||||||
|
|
||||||
|
|
||||||
<!-- Black backgrounds theme -->
|
<!-- Black backgrounds theme -->
|
||||||
<string name="use_black_backgrounds">Schwarze Hintergründe</string>
|
<string name="use_black_backgrounds">Schwarze Hintergründe</string>
|
||||||
<string name="use_black_backgrounds_description">Bei Verwendung des dunklen Designs, schwarze Hintergründe verwenden.</string>
|
<string name="use_black_backgrounds_description">Bei Verwendung des dunklen Designs, schwarze Hintergründe verwenden.</string>
|
||||||
|
|
||||||
<!-- Buttons -->
|
|
||||||
<string name="enable_folder_button">Ordner</string>
|
|
||||||
<string name="enable_qlaunch_button">QLaunch</string>
|
|
||||||
<!-- App Language -->
|
<!-- App Language -->
|
||||||
<string name="app_language">App-Sprache</string>
|
<string name="app_language">App-Sprache</string>
|
||||||
<string name="app_language_description">Sprache der App-Oberfläche ändern</string>
|
<string name="app_language_description">Sprache der App-Oberfläche ändern</string>
|
||||||
<string name="app_language_system">System folgen</string>
|
<string name="app_language_system">System folgen</string>
|
||||||
<!-- Static Themes -->
|
<!-- Static Themes -->
|
||||||
<string name="static_theme_color">Designfarbe</string>
|
<string name="static_theme_color">Designfarbe</string>
|
||||||
<string name="eden_theme">Eden</string>
|
|
||||||
<string name="violet">Violett </string>
|
<string name="violet">Violett </string>
|
||||||
<string name="blue">Blau</string>
|
<string name="blue">Blau</string>
|
||||||
<string name="cyan">Cyan</string>
|
<string name="cyan">Cyan</string>
|
||||||
<string name="red">Rot</string>
|
<string name="red">Rot</string>
|
||||||
<string name="green">Grün</string>
|
|
||||||
<string name="yellow">Gelb</string>
|
<string name="yellow">Gelb</string>
|
||||||
<string name="orange">Orange</string>
|
<string name="orange">Orange</string>
|
||||||
<string name="pink">Rosa</string>
|
<string name="pink">Rosa</string>
|
||||||
@@ -1099,10 +1037,6 @@ Wirklich fortfahren?</string>
|
|||||||
<string name="enable_overlay">Applet-Overlay aktivieren</string>
|
<string name="enable_overlay">Applet-Overlay aktivieren</string>
|
||||||
<string name="enable_overlay_description">Aktiviert Horizons eingebautes Overlay-Applet. Halte die Home-Taste eine Sekunde lang gedrückt, um es anzuzeigen.</string>
|
<string name="enable_overlay_description">Aktiviert Horizons eingebautes Overlay-Applet. Halte die Home-Taste eine Sekunde lang gedrückt, um es anzuzeigen.</string>
|
||||||
|
|
||||||
<!-- Profile Management -->
|
|
||||||
<string name="profile_manager">Nutzerverwaltung</string>
|
|
||||||
<string name="error">Fehler</string>
|
|
||||||
|
|
||||||
<!-- Licenses screen strings -->
|
<!-- Licenses screen strings -->
|
||||||
<string name="licenses">Lizenzen</string>
|
<string name="licenses">Lizenzen</string>
|
||||||
<string name="license_fidelityfx_fsr_description">Hochwertiges Upscaling von AMD</string>
|
<string name="license_fidelityfx_fsr_description">Hochwertiges Upscaling von AMD</string>
|
||||||
|
|||||||
@@ -106,6 +106,7 @@
|
|||||||
|
|
||||||
<!-- NVDEC Emulation -->
|
<!-- NVDEC Emulation -->
|
||||||
<string name="nvdec_emulation">Emulación NVDEC</string>
|
<string name="nvdec_emulation">Emulación NVDEC</string>
|
||||||
|
<string name="nvdec_emulation_description">Seleccione cómo se maneja la decodificación de vídeo (NVDEC) durante las escenas y las introducciones.</string>
|
||||||
<string name="nvdec_emulation_none">Ninguno</string>
|
<string name="nvdec_emulation_none">Ninguno</string>
|
||||||
|
|
||||||
<!-- Optimize SPIRV output -->
|
<!-- Optimize SPIRV output -->
|
||||||
@@ -291,41 +292,22 @@
|
|||||||
<string name="gpu_driver_manager">Gestor de controladores de la GPU</string>
|
<string name="gpu_driver_manager">Gestor de controladores de la GPU</string>
|
||||||
<string name="install_gpu_driver_description">Instale los controladores alternativos para obtener un posible mejor rendimiento o precisión</string>
|
<string name="install_gpu_driver_description">Instale los controladores alternativos para obtener un posible mejor rendimiento o precisión</string>
|
||||||
<string name="frame_gen">Generación de fotograma</string>
|
<string name="frame_gen">Generación de fotograma</string>
|
||||||
<string name="frame_gen_per_game_description">Configurar la generación de fotogramas para este juego</string>
|
|
||||||
<string name="frame_gen_multiplier">Multiplicador de fotograma</string>
|
<string name="frame_gen_multiplier">Multiplicador de fotograma</string>
|
||||||
<string name="frame_gen_multiplier_2x">2x</string>
|
<string name="frame_gen_multiplier_2x">2x</string>
|
||||||
<string name="frame_gen_multiplier_3x">3x</string>
|
<string name="frame_gen_multiplier_3x">3x</string>
|
||||||
<string name="frame_gen_multiplier_4x">4x</string>
|
<string name="frame_gen_multiplier_4x">4x</string>
|
||||||
<string name="frame_gen_target_rate">Objetivo de tasa de fotogramas</string>
|
|
||||||
<string name="frame_gen_target_rate_off">Usar un multiplicador fijo</string>
|
|
||||||
<string name="frame_gen_target_rate_60">60 FPS</string>
|
<string name="frame_gen_target_rate_60">60 FPS</string>
|
||||||
<string name="frame_gen_target_rate_90">90 FPS</string>
|
<string name="frame_gen_target_rate_90">90 FPS</string>
|
||||||
<string name="frame_gen_target_rate_120">120 FPS</string>
|
<string name="frame_gen_target_rate_120">120 FPS</string>
|
||||||
<string name="frame_gen_target_rate_144">144 FPS</string>
|
<string name="frame_gen_target_rate_144">144 FPS</string>
|
||||||
<string name="frame_gen_target_rate_165">165 FPS</string>
|
<string name="frame_gen_target_rate_165">165 FPS</string>
|
||||||
<string name="frame_gen_queue_target_0">Latencia más baja (Sin búfer)</string>
|
|
||||||
<string name="frame_gen_queue_target_1">Equilibrado (1 fotograma)</string>
|
<string name="frame_gen_queue_target_1">Equilibrado (1 fotograma)</string>
|
||||||
<string name="frame_gen_queue_target_2">Más suave (2 fotogramas)</string>
|
|
||||||
<string name="frame_gen_fp16">Sombreadores de media precisión</string>
|
|
||||||
<string name="frame_gen_unsupported">Generación de fotogramas no disponbile</string>
|
|
||||||
<string name="lossless_scaling_install">Instalar Lossless.dll</string>
|
|
||||||
<string name="lossless_scaling_replace_description">Seleccionar una copia diferente de Lossless.dll</string>
|
|
||||||
<string name="frame_generation_support">Generación de fotograma</string>
|
<string name="frame_generation_support">Generación de fotograma</string>
|
||||||
<string name="frame_generation_supported">Soportado</string>
|
<string name="frame_generation_supported">Soportado</string>
|
||||||
<string name="frame_generation_unsupported">No soportado (sin modelo de memoria de Vulkan)</string>
|
|
||||||
<string name="lossless_scaling">Escalado sin pérdidas</string>
|
<string name="lossless_scaling">Escalado sin pérdidas</string>
|
||||||
<string name="lossless_scaling_installed">Instalado</string>
|
<string name="lossless_scaling_installed">Instalado</string>
|
||||||
<string name="lossless_scaling_not_installed">No instalado</string>
|
<string name="lossless_scaling_not_installed">No instalado</string>
|
||||||
<string name="lossless_scaling_replace">Reemplazar</string>
|
|
||||||
<string name="lossless_scaling_remove">Borrar</string>
|
|
||||||
<string name="lossless_scaling_remove_description">Borrar Lossless.dll instalado y sus sombreadores preparados</string>
|
|
||||||
<string name="lossless_scaling_missing">Lossless.dll no instalado</string>
|
<string name="lossless_scaling_missing">Lossless.dll no instalado</string>
|
||||||
<string name="lossless_scaling_locked">Primero cierra el juego</string>
|
|
||||||
<string name="lossless_scaling_remove_unavailable">Nada que borrar</string>
|
|
||||||
<string name="lossless_scaling_install_success">Lossless.dll instalado correctamente</string>
|
|
||||||
<string name="lossless_scaling_install_failed">No se pudo instalar Lossless.dll</string>
|
|
||||||
<string name="error_lossless_copy_failed">No se pudo copiar el archivo seleccionado.</string>
|
|
||||||
<string name="error_lossless_unreadable">No se pudo leer el archivo seleccionado.</string>
|
|
||||||
<string name="advanced_settings">Ajustes avanzados</string>
|
<string name="advanced_settings">Ajustes avanzados</string>
|
||||||
<string name="settings_description">Configurar los ajustes del emulador</string>
|
<string name="settings_description">Configurar los ajustes del emulador</string>
|
||||||
<string name="search_recently_played">Jugado recientemente</string>
|
<string name="search_recently_played">Jugado recientemente</string>
|
||||||
@@ -472,8 +454,6 @@
|
|||||||
<string name="use_custom_rtc_description">Le permite tener un reloj personalizado en tiempo real diferente de la hora de su sistema.</string>
|
<string name="use_custom_rtc_description">Le permite tener un reloj personalizado en tiempo real diferente de la hora de su sistema.</string>
|
||||||
<string name="set_custom_rtc">Configurar RTC personalizado</string>
|
<string name="set_custom_rtc">Configurar RTC personalizado</string>
|
||||||
|
|
||||||
<!-- CPU -->
|
|
||||||
<string name="fast_cpu_time">Relojes de la CPU</string>
|
|
||||||
<string name="custom_cpu_ticks">Ticks de CPU personalizados</string>
|
<string name="custom_cpu_ticks">Ticks de CPU personalizados</string>
|
||||||
<string name="custom_cpu_ticks_description">Establezca un valor personalizado de los ciclos de la CPU. Los valores más altos pueden aumentar el rendimiento, pero también pueden hacer que el juego se congele. Se recomienda un rango de 77–21000.</string>
|
<string name="custom_cpu_ticks_description">Establezca un valor personalizado de los ciclos de la CPU. Los valores más altos pueden aumentar el rendimiento, pero también pueden hacer que el juego se congele. Se recomienda un rango de 77–21000.</string>
|
||||||
<string name="cpu_ticks">Ciclos</string>
|
<string name="cpu_ticks">Ciclos</string>
|
||||||
@@ -532,7 +512,6 @@
|
|||||||
|
|
||||||
<string name="hacks">Hacks</string>
|
<string name="hacks">Hacks</string>
|
||||||
|
|
||||||
<string name="fast_gpu_time">Relojes de la GPU</string>
|
|
||||||
<string name="skip_cpu_inner_invalidation">Omitir invalidación interna de la CPU</string>
|
<string name="skip_cpu_inner_invalidation">Omitir invalidación interna de la CPU</string>
|
||||||
<string name="skip_cpu_inner_invalidation_description">Omite ciertas invalidaciones de caché de la CPU durante las actualizaciones de memoria, lo que reduce el uso de la CPU y mejora su rendimiento. Esto puede causar fallos o bloqueos en algunos juegos.</string>
|
<string name="skip_cpu_inner_invalidation_description">Omite ciertas invalidaciones de caché de la CPU durante las actualizaciones de memoria, lo que reduce el uso de la CPU y mejora su rendimiento. Esto puede causar fallos o bloqueos en algunos juegos.</string>
|
||||||
<string name="fix_bloom_effects">Arreglar los efectos de resplandor</string>
|
<string name="fix_bloom_effects">Arreglar los efectos de resplandor</string>
|
||||||
@@ -579,7 +558,6 @@
|
|||||||
|
|
||||||
<!-- Debug settings strings -->
|
<!-- Debug settings strings -->
|
||||||
<string name="cpu">CPU</string>
|
<string name="cpu">CPU</string>
|
||||||
<string name="clocks">Relojes</string>
|
|
||||||
<string name="use_auto_stub">Usar Auto Stub</string>
|
<string name="use_auto_stub">Usar Auto Stub</string>
|
||||||
<string name="use_auto_stub_description">Rellena automáticamente servicios y funciones ausentes. Puede mejorar la compatibilidad pero puede causar cierres inesperados.</string>
|
<string name="use_auto_stub_description">Rellena automáticamente servicios y funciones ausentes. Puede mejorar la compatibilidad pero puede causar cierres inesperados.</string>
|
||||||
|
|
||||||
@@ -594,8 +572,6 @@
|
|||||||
<string name="log">Registro</string>
|
<string name="log">Registro</string>
|
||||||
<string name="flush_by_line">Vaciar los registros de depuración por línea</string>
|
<string name="flush_by_line">Vaciar los registros de depuración por línea</string>
|
||||||
<string name="flush_by_line_description">Vacía los registros de depuración en cada línea escrita, facilitando la depuración en casos de bloqueos o congelamientos.</string>
|
<string name="flush_by_line_description">Vacía los registros de depuración en cada línea escrita, facilitando la depuración en casos de bloqueos o congelamientos.</string>
|
||||||
<string name="log_filter">Filtro de registros</string>
|
|
||||||
<string name="log_filter_description">Controla las categorias de registros de Eden. Por ejemplo: *:Info Service.LM:Debug</string>
|
|
||||||
|
|
||||||
<!-- GPU Logging strings -->
|
<!-- GPU Logging strings -->
|
||||||
<string name="gpu_logging_header">Registros de la GPU</string>
|
<string name="gpu_logging_header">Registros de la GPU</string>
|
||||||
@@ -983,12 +959,10 @@
|
|||||||
|
|
||||||
<!-- CPU clock levels -->
|
<!-- CPU clock levels -->
|
||||||
<string name="clock_normal">Normal</string>
|
<string name="clock_normal">Normal</string>
|
||||||
<string name="clock_boost">Impulso</string>
|
|
||||||
<string name="clock_fast">Overclock</string>
|
<string name="clock_fast">Overclock</string>
|
||||||
|
|
||||||
<!-- GPU clock levels -->
|
<!-- GPU clock levels -->
|
||||||
<string name="fast_gpu_normal">Normal</string>
|
<string name="fast_gpu_normal">Normal</string>
|
||||||
<string name="fast_gpu_medium">Impulso</string>
|
|
||||||
<string name="fast_gpu_high">Overclock</string>
|
<string name="fast_gpu_high">Overclock</string>
|
||||||
|
|
||||||
<!-- GPU swizzle texture size -->
|
<!-- GPU swizzle texture size -->
|
||||||
@@ -1118,6 +1092,7 @@
|
|||||||
<string name="theme_mode_light">Claro</string>
|
<string name="theme_mode_light">Claro</string>
|
||||||
<string name="theme_mode_dark">Oscuro</string>
|
<string name="theme_mode_dark">Oscuro</string>
|
||||||
|
|
||||||
|
|
||||||
<!-- Black backgrounds theme -->
|
<!-- Black backgrounds theme -->
|
||||||
<string name="use_black_backgrounds">Fondos oscuros</string>
|
<string name="use_black_backgrounds">Fondos oscuros</string>
|
||||||
<string name="use_black_backgrounds_description">Cuando se usa el modo oscuro, aplicar fondos de pantalla negros.</string>
|
<string name="use_black_backgrounds_description">Cuando se usa el modo oscuro, aplicar fondos de pantalla negros.</string>
|
||||||
|
|||||||
@@ -104,6 +104,7 @@
|
|||||||
|
|
||||||
<!-- NVDEC Emulation -->
|
<!-- NVDEC Emulation -->
|
||||||
<string name="nvdec_emulation">Émulation NVDEC</string>
|
<string name="nvdec_emulation">Émulation NVDEC</string>
|
||||||
|
<string name="nvdec_emulation_description">Sélectionnez la manière dont le décodage vidéo (NVDEC) est géré pendant les cinématiques et les intros.</string>
|
||||||
<string name="nvdec_emulation_none">Aucun</string>
|
<string name="nvdec_emulation_none">Aucun</string>
|
||||||
|
|
||||||
<!-- Optimize SPIRV output -->
|
<!-- Optimize SPIRV output -->
|
||||||
@@ -517,6 +518,7 @@
|
|||||||
<string name="log">Journalisation</string>
|
<string name="log">Journalisation</string>
|
||||||
<string name="flush_by_line">Vider les journaux de débogage ligne par ligne</string>
|
<string name="flush_by_line">Vider les journaux de débogage ligne par ligne</string>
|
||||||
<string name="flush_by_line_description">Vide les journaux de débogage à chaque ligne écrite, facilitant le débogage en cas de plantage ou de gel.</string>
|
<string name="flush_by_line_description">Vide les journaux de débogage à chaque ligne écrite, facilitant le débogage en cas de plantage ou de gel.</string>
|
||||||
|
|
||||||
<!-- GPU Logging strings -->
|
<!-- GPU Logging strings -->
|
||||||
<string name="gpu_logging_header">Journalisation GPU</string>
|
<string name="gpu_logging_header">Journalisation GPU</string>
|
||||||
<string name="gpu_log_level">Niveau de journalisation</string>
|
<string name="gpu_log_level">Niveau de journalisation</string>
|
||||||
@@ -1002,6 +1004,7 @@
|
|||||||
<string name="theme_mode_light">Lumineux</string>
|
<string name="theme_mode_light">Lumineux</string>
|
||||||
<string name="theme_mode_dark">Sombre</string>
|
<string name="theme_mode_dark">Sombre</string>
|
||||||
|
|
||||||
|
|
||||||
<!-- Black backgrounds theme -->
|
<!-- Black backgrounds theme -->
|
||||||
<string name="use_black_backgrounds">Arrière-plan noir</string>
|
<string name="use_black_backgrounds">Arrière-plan noir</string>
|
||||||
<string name="use_black_backgrounds_description">Lorsque vous utilisez le thème sombre, appliquer un arrière-plan noir.</string>
|
<string name="use_black_backgrounds_description">Lorsque vous utilisez le thème sombre, appliquer un arrière-plan noir.</string>
|
||||||
|
|||||||
@@ -67,6 +67,7 @@
|
|||||||
<string name="debug_knobs_description">לשימוש בפיתוח בלבד.</string>
|
<string name="debug_knobs_description">לשימוש בפיתוח בלבד.</string>
|
||||||
<!-- NVDEC Emulation -->
|
<!-- NVDEC Emulation -->
|
||||||
<string name="nvdec_emulation">אמולציית NVDEC</string>
|
<string name="nvdec_emulation">אמולציית NVDEC</string>
|
||||||
|
<string name="nvdec_emulation_description">בחר כיצד לטפל בפענוח וידאו</string>
|
||||||
<string name="nvdec_emulation_none">ללא</string>
|
<string name="nvdec_emulation_none">ללא</string>
|
||||||
|
|
||||||
<!-- Optimize SPIRV output -->
|
<!-- Optimize SPIRV output -->
|
||||||
@@ -407,6 +408,7 @@
|
|||||||
<string name="log">רישום</string>
|
<string name="log">רישום</string>
|
||||||
<string name="flush_by_line">רוקן יומני ניפוי שגיאות לפי שורה</string>
|
<string name="flush_by_line">רוקן יומני ניפוי שגיאות לפי שורה</string>
|
||||||
<string name="flush_by_line_description">מרוקן יומני ניפוי שגיאות בכל שורה שנכתבת, מה שמקל על ניפוי שגיאות במקרים של קריסה או קיפאון.</string>
|
<string name="flush_by_line_description">מרוקן יומני ניפוי שגיאות בכל שורה שנכתבת, מה שמקל על ניפוי שגיאות במקרים של קריסה או קיפאון.</string>
|
||||||
|
|
||||||
<!-- Audio settings strings -->
|
<!-- Audio settings strings -->
|
||||||
<string name="audio_output_engine">מנוע פלט</string>
|
<string name="audio_output_engine">מנוע פלט</string>
|
||||||
<string name="audio_volume">עוצמת שמע</string>
|
<string name="audio_volume">עוצמת שמע</string>
|
||||||
|
|||||||
@@ -62,6 +62,7 @@
|
|||||||
<string name="cpuopt_unsafe_host_mmu_description">Ez az optimalizáció gyorsítja a vendégprogram memória-hozzáférését. Engedélyezése esetén a vendég memóriaolvasási/írási műveletei közvetlenül a memóriában történnek, és kihasználják a gazda MMU-ját. Letiltás esetén minden memória-hozzáférés a szoftveres MMU emulációt használja.</string>
|
<string name="cpuopt_unsafe_host_mmu_description">Ez az optimalizáció gyorsítja a vendégprogram memória-hozzáférését. Engedélyezése esetén a vendég memóriaolvasási/írási műveletei közvetlenül a memóriában történnek, és kihasználják a gazda MMU-ját. Letiltás esetén minden memória-hozzáférés a szoftveres MMU emulációt használja.</string>
|
||||||
<!-- NVDEC Emulation -->
|
<!-- NVDEC Emulation -->
|
||||||
<string name="nvdec_emulation">NVDEC emuláció</string>
|
<string name="nvdec_emulation">NVDEC emuláció</string>
|
||||||
|
<string name="nvdec_emulation_description">Videódekódolás kezelése</string>
|
||||||
<string name="nvdec_emulation_none">Nincs</string>
|
<string name="nvdec_emulation_none">Nincs</string>
|
||||||
|
|
||||||
<!-- Optimize SPIRV output -->
|
<!-- Optimize SPIRV output -->
|
||||||
@@ -395,6 +396,7 @@
|
|||||||
<string name="log">Naplózás</string>
|
<string name="log">Naplózás</string>
|
||||||
<string name="flush_by_line">Hibakeresési naplók soronkénti kiürítése</string>
|
<string name="flush_by_line">Hibakeresési naplók soronkénti kiürítése</string>
|
||||||
<string name="flush_by_line_description">Kiüríti a hibakeresési naplókat minden írt sor után, megkönnyítve a hibakeresést összeomlás vagy fagyás esetén.</string>
|
<string name="flush_by_line_description">Kiüríti a hibakeresési naplókat minden írt sor után, megkönnyítve a hibakeresést összeomlás vagy fagyás esetén.</string>
|
||||||
|
|
||||||
<!-- Audio settings strings -->
|
<!-- Audio settings strings -->
|
||||||
<string name="audio_output_engine">Kimeneti motor</string>
|
<string name="audio_output_engine">Kimeneti motor</string>
|
||||||
<string name="audio_volume">Hangerő</string>
|
<string name="audio_volume">Hangerő</string>
|
||||||
|
|||||||
@@ -81,6 +81,7 @@
|
|||||||
<string name="cpuopt_unsafe_host_mmu_description">Optimasi ini mempercepat akses memori oleh program tamu. Mengaktifkannya menyebabkan pembacaan/penulisan memori tamu dilakukan langsung ke memori dan memanfaatkan MMU Host. Menonaktifkan ini memaksa semua akses memori menggunakan Emulasi MMU Perangkat Lunak.</string>
|
<string name="cpuopt_unsafe_host_mmu_description">Optimasi ini mempercepat akses memori oleh program tamu. Mengaktifkannya menyebabkan pembacaan/penulisan memori tamu dilakukan langsung ke memori dan memanfaatkan MMU Host. Menonaktifkan ini memaksa semua akses memori menggunakan Emulasi MMU Perangkat Lunak.</string>
|
||||||
<!-- NVDEC Emulation -->
|
<!-- NVDEC Emulation -->
|
||||||
<string name="nvdec_emulation">Emulasi NVDEC</string>
|
<string name="nvdec_emulation">Emulasi NVDEC</string>
|
||||||
|
<string name="nvdec_emulation_description">Pilih cara decoding video (NVDEC) ditangani selama cutscene dan intro.</string>
|
||||||
<string name="nvdec_emulation_none">Tidak Ada</string>
|
<string name="nvdec_emulation_none">Tidak Ada</string>
|
||||||
|
|
||||||
<!-- Optimize SPIRV output -->
|
<!-- Optimize SPIRV output -->
|
||||||
@@ -429,6 +430,7 @@
|
|||||||
<string name="log">Pencatatan</string>
|
<string name="log">Pencatatan</string>
|
||||||
<string name="flush_by_line">Buang log debug per baris</string>
|
<string name="flush_by_line">Buang log debug per baris</string>
|
||||||
<string name="flush_by_line_description">Membuang log debug pada setiap baris yang ditulis, memudahkan debugging dalam kasus crash atau freeze.</string>
|
<string name="flush_by_line_description">Membuang log debug pada setiap baris yang ditulis, memudahkan debugging dalam kasus crash atau freeze.</string>
|
||||||
|
|
||||||
<!-- Audio settings strings -->
|
<!-- Audio settings strings -->
|
||||||
<string name="audio_output_engine">Output audio</string>
|
<string name="audio_output_engine">Output audio</string>
|
||||||
<string name="audio_volume">Volume</string>
|
<string name="audio_volume">Volume</string>
|
||||||
|
|||||||
@@ -79,6 +79,7 @@
|
|||||||
<string name="cpuopt_unsafe_host_mmu_description">Questa ottimizzazione accelera gli accessi alla memoria da parte del programma guest. Abilitandola, le letture/scritture della memoria guest vengono eseguite direttamente in memoria e sfruttano la MMU host. Disabilitandola, tutti gli accessi alla memoria sono costretti a utilizzare l\'emulazione software della MMU.</string>
|
<string name="cpuopt_unsafe_host_mmu_description">Questa ottimizzazione accelera gli accessi alla memoria da parte del programma guest. Abilitandola, le letture/scritture della memoria guest vengono eseguite direttamente in memoria e sfruttano la MMU host. Disabilitandola, tutti gli accessi alla memoria sono costretti a utilizzare l\'emulazione software della MMU.</string>
|
||||||
<!-- NVDEC Emulation -->
|
<!-- NVDEC Emulation -->
|
||||||
<string name="nvdec_emulation">Emulazione NVDEC</string>
|
<string name="nvdec_emulation">Emulazione NVDEC</string>
|
||||||
|
<string name="nvdec_emulation_description">Scegli come gestire la decodifica video</string>
|
||||||
<string name="nvdec_emulation_none">Nessuna</string>
|
<string name="nvdec_emulation_none">Nessuna</string>
|
||||||
|
|
||||||
<!-- Optimize SPIRV output -->
|
<!-- Optimize SPIRV output -->
|
||||||
@@ -436,6 +437,7 @@
|
|||||||
<string name="log">Registrazione</string>
|
<string name="log">Registrazione</string>
|
||||||
<string name="flush_by_line">Svuota i log di debug per riga</string>
|
<string name="flush_by_line">Svuota i log di debug per riga</string>
|
||||||
<string name="flush_by_line_description">Svuota i log di debug su ogni riga scritta, facilitando il debug in caso di crash o blocco.</string>
|
<string name="flush_by_line_description">Svuota i log di debug su ogni riga scritta, facilitando il debug in caso di crash o blocco.</string>
|
||||||
|
|
||||||
<!-- Audio settings strings -->
|
<!-- Audio settings strings -->
|
||||||
<string name="audio_output_engine">Motore di Output</string>
|
<string name="audio_output_engine">Motore di Output</string>
|
||||||
<string name="audio_volume">Volume</string>
|
<string name="audio_volume">Volume</string>
|
||||||
|
|||||||
@@ -62,6 +62,7 @@
|
|||||||
<string name="cpuopt_unsafe_host_mmu_description">この最適化により、ゲストプログラムによるメモリアクセスが高速化されます。有効にすると、ゲストのメモリ読み書きが直接メモリ内で実行され、ホストのMMUを利用します。無効にすると、すべてのメモリアクセスでソフトウェアMMUエミュレーションが使用されます。</string>
|
<string name="cpuopt_unsafe_host_mmu_description">この最適化により、ゲストプログラムによるメモリアクセスが高速化されます。有効にすると、ゲストのメモリ読み書きが直接メモリ内で実行され、ホストのMMUを利用します。無効にすると、すべてのメモリアクセスでソフトウェアMMUエミュレーションが使用されます。</string>
|
||||||
<!-- NVDEC Emulation -->
|
<!-- NVDEC Emulation -->
|
||||||
<string name="nvdec_emulation">NVDECエミュレーション</string>
|
<string name="nvdec_emulation">NVDECエミュレーション</string>
|
||||||
|
<string name="nvdec_emulation_description">ビデオデコード方法</string>
|
||||||
<string name="nvdec_emulation_none">無効</string>
|
<string name="nvdec_emulation_none">無効</string>
|
||||||
|
|
||||||
<!-- Optimize SPIRV output -->
|
<!-- Optimize SPIRV output -->
|
||||||
@@ -397,6 +398,7 @@
|
|||||||
<string name="log">ロギング</string>
|
<string name="log">ロギング</string>
|
||||||
<string name="flush_by_line">デバッグログを行ごとにフラッシュ</string>
|
<string name="flush_by_line">デバッグログを行ごとにフラッシュ</string>
|
||||||
<string name="flush_by_line_description">デバッグログを行ごとにフラッシュし、クラッシュやフリーズ時のデバッグを容易にします。</string>
|
<string name="flush_by_line_description">デバッグログを行ごとにフラッシュし、クラッシュやフリーズ時のデバッグを容易にします。</string>
|
||||||
|
|
||||||
<!-- Audio settings strings -->
|
<!-- Audio settings strings -->
|
||||||
<string name="audio_output_engine">出力エンジン</string>
|
<string name="audio_output_engine">出力エンジン</string>
|
||||||
<string name="audio_volume">音量</string>
|
<string name="audio_volume">音量</string>
|
||||||
|
|||||||
@@ -62,6 +62,7 @@
|
|||||||
<string name="cpuopt_unsafe_host_mmu_description">이 최적화는 게스트 프로그램의 메모리 접근 속도를 높입니다. 활성화하면 게스트의 메모리 읽기/쓰기가 메모리에서 직접 수행되고 호스트의 MMU를 활용합니다. 비활성화하면 모든 메모리 접근에 소프트웨어 MMU 에뮬레이션을 사용하게 됩니다.</string>
|
<string name="cpuopt_unsafe_host_mmu_description">이 최적화는 게스트 프로그램의 메모리 접근 속도를 높입니다. 활성화하면 게스트의 메모리 읽기/쓰기가 메모리에서 직접 수행되고 호스트의 MMU를 활용합니다. 비활성화하면 모든 메모리 접근에 소프트웨어 MMU 에뮬레이션을 사용하게 됩니다.</string>
|
||||||
<!-- NVDEC Emulation -->
|
<!-- NVDEC Emulation -->
|
||||||
<string name="nvdec_emulation">NVDEC 에뮬레이션</string>
|
<string name="nvdec_emulation">NVDEC 에뮬레이션</string>
|
||||||
|
<string name="nvdec_emulation_description">비디오 디코딩 처리 방식 선택</string>
|
||||||
<string name="nvdec_emulation_none">없음</string>
|
<string name="nvdec_emulation_none">없음</string>
|
||||||
|
|
||||||
<!-- Optimize SPIRV output -->
|
<!-- Optimize SPIRV output -->
|
||||||
@@ -397,6 +398,7 @@
|
|||||||
<string name="log">로깅</string>
|
<string name="log">로깅</string>
|
||||||
<string name="flush_by_line">디버그 로그를 줄별로 플러시</string>
|
<string name="flush_by_line">디버그 로그를 줄별로 플러시</string>
|
||||||
<string name="flush_by_line_description">디버그 로그를 각 줄마다 플러시하여 충돌 또는 정지 시 디버깅을 용이하게 합니다.</string>
|
<string name="flush_by_line_description">디버그 로그를 각 줄마다 플러시하여 충돌 또는 정지 시 디버깅을 용이하게 합니다.</string>
|
||||||
|
|
||||||
<!-- Audio settings strings -->
|
<!-- Audio settings strings -->
|
||||||
<string name="audio_output_engine">출력 엔진</string>
|
<string name="audio_output_engine">출력 엔진</string>
|
||||||
<string name="audio_volume">볼륨</string>
|
<string name="audio_volume">볼륨</string>
|
||||||
|
|||||||
@@ -62,6 +62,7 @@
|
|||||||
<string name="cpuopt_unsafe_host_mmu_description">Denne optimaliseringen fremskynder minnetilgang av gjesteprogrammet. Hvis aktivert, utføres gjestens minnelesing/skriving direkte i minnet og bruker vertens MMU. Deaktivering tvinger alle minnetilganger til å bruke programvarebasert MMU-emulering.</string>
|
<string name="cpuopt_unsafe_host_mmu_description">Denne optimaliseringen fremskynder minnetilgang av gjesteprogrammet. Hvis aktivert, utføres gjestens minnelesing/skriving direkte i minnet og bruker vertens MMU. Deaktivering tvinger alle minnetilganger til å bruke programvarebasert MMU-emulering.</string>
|
||||||
<!-- NVDEC Emulation -->
|
<!-- NVDEC Emulation -->
|
||||||
<string name="nvdec_emulation">NVDEC-emulering</string>
|
<string name="nvdec_emulation">NVDEC-emulering</string>
|
||||||
|
<string name="nvdec_emulation_description">Velg hvordan videodekoding håndteres</string>
|
||||||
<string name="nvdec_emulation_none">Ingen</string>
|
<string name="nvdec_emulation_none">Ingen</string>
|
||||||
|
|
||||||
<!-- Optimize SPIRV output -->
|
<!-- Optimize SPIRV output -->
|
||||||
@@ -378,6 +379,7 @@
|
|||||||
<string name="log">Logging</string>
|
<string name="log">Logging</string>
|
||||||
<string name="flush_by_line">Tøm feilsøkingslogger per linje</string>
|
<string name="flush_by_line">Tøm feilsøkingslogger per linje</string>
|
||||||
<string name="flush_by_line_description">Tømmer feilsøkingslogger for hver linje som skrives, noe som gjør feilsøking enklere ved krasj eller frysing.</string>
|
<string name="flush_by_line_description">Tømmer feilsøkingslogger for hver linje som skrives, noe som gjør feilsøking enklere ved krasj eller frysing.</string>
|
||||||
|
|
||||||
<!-- Audio settings strings -->
|
<!-- Audio settings strings -->
|
||||||
<string name="audio_output_engine">Lydmotor</string>
|
<string name="audio_output_engine">Lydmotor</string>
|
||||||
<string name="audio_volume">Volum</string>
|
<string name="audio_volume">Volum</string>
|
||||||
|
|||||||
@@ -97,6 +97,7 @@
|
|||||||
|
|
||||||
<!-- NVDEC Emulation -->
|
<!-- NVDEC Emulation -->
|
||||||
<string name="nvdec_emulation">Emulacja NVDEC</string>
|
<string name="nvdec_emulation">Emulacja NVDEC</string>
|
||||||
|
<string name="nvdec_emulation_description">Wybierz metodę dekodowania wideo (NVDEC).</string>
|
||||||
<string name="nvdec_emulation_none">Brak</string>
|
<string name="nvdec_emulation_none">Brak</string>
|
||||||
|
|
||||||
<!-- Optimize SPIRV output -->
|
<!-- Optimize SPIRV output -->
|
||||||
@@ -499,6 +500,7 @@
|
|||||||
<string name="log">Rejestrowanie</string>
|
<string name="log">Rejestrowanie</string>
|
||||||
<string name="flush_by_line">Opróżniaj dzienniki debugowania linia po linii</string>
|
<string name="flush_by_line">Opróżniaj dzienniki debugowania linia po linii</string>
|
||||||
<string name="flush_by_line_description">Opróżnia dzienniki debugowania po każdej napisanej linii, ułatwiając debugowanie w przypadku awarii lub zawieszenia.</string>
|
<string name="flush_by_line_description">Opróżnia dzienniki debugowania po każdej napisanej linii, ułatwiając debugowanie w przypadku awarii lub zawieszenia.</string>
|
||||||
|
|
||||||
<string name="general">Ogólne</string>
|
<string name="general">Ogólne</string>
|
||||||
|
|
||||||
<!-- Audio settings strings -->
|
<!-- Audio settings strings -->
|
||||||
@@ -933,6 +935,7 @@
|
|||||||
<string name="theme_mode_light">Jasny</string>
|
<string name="theme_mode_light">Jasny</string>
|
||||||
<string name="theme_mode_dark">Ciemny</string>
|
<string name="theme_mode_dark">Ciemny</string>
|
||||||
|
|
||||||
|
|
||||||
<!-- Black backgrounds theme -->
|
<!-- Black backgrounds theme -->
|
||||||
<string name="use_black_backgrounds">Czarne tła</string>
|
<string name="use_black_backgrounds">Czarne tła</string>
|
||||||
<string name="use_black_backgrounds_description">Kiedy używany ciemny motyw, tła zostają zastąpione czernią.</string>
|
<string name="use_black_backgrounds_description">Kiedy używany ciemny motyw, tła zostają zastąpione czernią.</string>
|
||||||
|
|||||||
@@ -91,6 +91,7 @@
|
|||||||
|
|
||||||
<!-- NVDEC Emulation -->
|
<!-- NVDEC Emulation -->
|
||||||
<string name="nvdec_emulation">Decodificação de Vídeo (NVDEC)</string>
|
<string name="nvdec_emulation">Decodificação de Vídeo (NVDEC)</string>
|
||||||
|
<string name="nvdec_emulation_description">Selecione como a decodificação de vídeo é realizada durante cutscenes e intros.</string>
|
||||||
<string name="nvdec_emulation_none">Nenhum</string>
|
<string name="nvdec_emulation_none">Nenhum</string>
|
||||||
|
|
||||||
<!-- Optimize SPIRV output -->
|
<!-- Optimize SPIRV output -->
|
||||||
@@ -482,6 +483,7 @@
|
|||||||
<string name="log">Registro</string>
|
<string name="log">Registro</string>
|
||||||
<string name="flush_by_line">Liberar logs de depuração por linha</string>
|
<string name="flush_by_line">Liberar logs de depuração por linha</string>
|
||||||
<string name="flush_by_line_description">Libera logs de depuração em cada linha escrita, facilitando a depuração em casos de travamento ou congelamento.</string>
|
<string name="flush_by_line_description">Libera logs de depuração em cada linha escrita, facilitando a depuração em casos de travamento ou congelamento.</string>
|
||||||
|
|
||||||
<string name="general">Geral</string>
|
<string name="general">Geral</string>
|
||||||
|
|
||||||
<!-- Audio settings strings -->
|
<!-- Audio settings strings -->
|
||||||
@@ -889,6 +891,7 @@
|
|||||||
<string name="theme_mode_light">Claro</string>
|
<string name="theme_mode_light">Claro</string>
|
||||||
<string name="theme_mode_dark">Escuro</string>
|
<string name="theme_mode_dark">Escuro</string>
|
||||||
|
|
||||||
|
|
||||||
<!-- Black backgrounds theme -->
|
<!-- Black backgrounds theme -->
|
||||||
<string name="use_black_backgrounds">Planos de fundo pretos</string>
|
<string name="use_black_backgrounds">Planos de fundo pretos</string>
|
||||||
<string name="use_black_backgrounds_description">Quando usar o tema escuro, aplicar fundos pretos</string>
|
<string name="use_black_backgrounds_description">Quando usar o tema escuro, aplicar fundos pretos</string>
|
||||||
|
|||||||
@@ -62,6 +62,7 @@
|
|||||||
<string name="cpuopt_unsafe_host_mmu_description">Esta otimização acelera os acessos à memória pelo programa convidado. Ativar faz com que as leituras/escritas de memória do convidado sejam efetuadas diretamente na memória e utilizem a MMU do Anfitrião. Desativar força todos os acessos à memória a usar a Emulação de MMU por Software.</string>
|
<string name="cpuopt_unsafe_host_mmu_description">Esta otimização acelera os acessos à memória pelo programa convidado. Ativar faz com que as leituras/escritas de memória do convidado sejam efetuadas diretamente na memória e utilizem a MMU do Anfitrião. Desativar força todos os acessos à memória a usar a Emulação de MMU por Software.</string>
|
||||||
<!-- NVDEC Emulation -->
|
<!-- NVDEC Emulation -->
|
||||||
<string name="nvdec_emulation">Emulação NVDEC</string>
|
<string name="nvdec_emulation">Emulação NVDEC</string>
|
||||||
|
<string name="nvdec_emulation_description">Método de decodificação de vídeo.</string>
|
||||||
<string name="nvdec_emulation_none">Nenhum</string>
|
<string name="nvdec_emulation_none">Nenhum</string>
|
||||||
|
|
||||||
<!-- Optimize SPIRV output -->
|
<!-- Optimize SPIRV output -->
|
||||||
@@ -401,6 +402,7 @@
|
|||||||
<string name="log">Registo</string>
|
<string name="log">Registo</string>
|
||||||
<string name="flush_by_line">Libertar registos de depuração por linha</string>
|
<string name="flush_by_line">Libertar registos de depuração por linha</string>
|
||||||
<string name="flush_by_line_description">Liberta registos de depuração em cada linha escrita, facilitando a depuração em casos de falha ou congelamento.</string>
|
<string name="flush_by_line_description">Liberta registos de depuração em cada linha escrita, facilitando a depuração em casos de falha ou congelamento.</string>
|
||||||
|
|
||||||
<!-- Audio settings strings -->
|
<!-- Audio settings strings -->
|
||||||
<string name="audio_output_engine">Motor de saída</string>
|
<string name="audio_output_engine">Motor de saída</string>
|
||||||
<string name="audio_volume">Volume</string>
|
<string name="audio_volume">Volume</string>
|
||||||
|
|||||||
@@ -106,7 +106,7 @@
|
|||||||
|
|
||||||
<!-- NVDEC Emulation -->
|
<!-- NVDEC Emulation -->
|
||||||
<string name="nvdec_emulation">Эмуляция NVDEC</string>
|
<string name="nvdec_emulation">Эмуляция NVDEC</string>
|
||||||
<string name="nvdec_emulation_description">Переключите на CPU, если происходит вылет на кат-сценах.</string>
|
<string name="nvdec_emulation_description">Обработка видео (ролики, интро)</string>
|
||||||
<string name="nvdec_emulation_none">Отключено</string>
|
<string name="nvdec_emulation_none">Отключено</string>
|
||||||
|
|
||||||
<!-- Optimize SPIRV output -->
|
<!-- Optimize SPIRV output -->
|
||||||
@@ -291,58 +291,6 @@
|
|||||||
<string name="gpu_driver_fetcher">Получение драйверов ГПУ</string>
|
<string name="gpu_driver_fetcher">Получение драйверов ГПУ</string>
|
||||||
<string name="gpu_driver_manager">Менеджер драйверов ГПУ</string>
|
<string name="gpu_driver_manager">Менеджер драйверов ГПУ</string>
|
||||||
<string name="install_gpu_driver_description">Установите альтернативные драйверы для потенциально лучшей производительности и/или точности</string>
|
<string name="install_gpu_driver_description">Установите альтернативные драйверы для потенциально лучшей производительности и/или точности</string>
|
||||||
<string name="frame_gen">Генерация кадров</string>
|
|
||||||
<string name="frame_gen_per_game_description">Настройка генерации кадров для данной игры</string>
|
|
||||||
<string name="frame_gen_description">Вставляет промежуточные кадры между отрендеренными с помощью Lossless Scaling. При включении принудительно устанавливает режим вывода FIFO.</string>
|
|
||||||
<string name="frame_gen_multiplier">Множитель кадров</string>
|
|
||||||
<string name="frame_gen_multiplier_description">Количество кадров, отображаемых на каждый отрисованный кадр. Повышение значения пропорционально увеличивает затраты ресурсов ГПУ. Если запрашивать больше, чем может отобразить ваш экран, эмуляция будет замедляться.</string>
|
|
||||||
<string name="frame_gen_target_rate">Целевая частота кадров</string>
|
|
||||||
<string name="frame_gen_target_rate_description">Выберите значение под ваш дисплей. Множитель подстроится сам, чтобы его держать, и откатит изменения, если игра начнёт тормозить.</string>
|
|
||||||
<string name="frame_gen_target_rate_off">Использовать фиксированный множитель</string>
|
|
||||||
<string name="frame_gen_queue_target">Целевой размер очереди кадров</string>
|
|
||||||
<string name="frame_gen_queue_target_description">Сколько готовых кадров может ожидать перед выводом на экран. Более длинные очереди сглаживают скачки ГПУ ценой задержки ввода.</string>
|
|
||||||
<string name="frame_gen_queue_target_0">Минимальная задержка (Без буферизации)</string>
|
|
||||||
<string name="frame_gen_queue_target_1">Сбалансированный (1 кадр)</string>
|
|
||||||
<string name="frame_gen_queue_target_2">Наиболее плавный (2 кадра)</string>
|
|
||||||
<string name="frame_gen_flow_scale_auto">Подстроить оценку движения под игру</string>
|
|
||||||
<string name="frame_gen_flow_scale_auto_description">Оценивать движение в разрешении, которое игра действительно рендерит, вместо масштабированного вывода. Ничего не стоит в точности, так как масштабирование не добавляет деталей движения.</string>
|
|
||||||
<string name="frame_gen_flow_scale">Разрешение оценки движения</string>
|
|
||||||
<string name="frame_gen_flow_scale_description">Разрешение прохода оптического потока в долях от выходного разрешения. Его понижение — самый дешёвый способ вернуть производительность.</string>
|
|
||||||
<string name="frame_gen_fp16">Шейдеры половинной точности</string>
|
|
||||||
<string name="frame_gen_fp16_description">Использовать 16-битную версию шейдеров. Автоматически переключается на обычную, если драйвер или файл не поддерживают её.</string>
|
|
||||||
<string name="frame_gen_dump_flow">Сохранить сгенерированный кадр</string>
|
|
||||||
<string name="frame_gen_dump_flow_description">Однократно записать уровни мип-карт оптического потока и интерполированный кадр в папку lossless/debug для диагностики.</string>
|
|
||||||
<string name="frame_gen_unsupported">Генерация кадров недоступна</string>
|
|
||||||
<string name="frame_gen_unsupported_description">Драйвер ГПУ не поддерживает модель памяти Vulkan, требуемую шейдерами Lossless Scaling.</string>
|
|
||||||
<string name="lossless_scaling_setup_description">Опционально. Укажите свой Lossless.dll для включения генерации кадров позже.</string>
|
|
||||||
<string name="lossless_scaling_install">Установить Lossless.dll</string>
|
|
||||||
<string name="lossless_scaling_install_description">Для генерации кадров требуется ваша собственная легальная копия Lossless.dll из Lossless Scaling</string>
|
|
||||||
<string name="lossless_scaling_replace_description">Выбрать другой файл Lossless.dll</string>
|
|
||||||
<string name="frame_generation_support">Генерация кадров</string>
|
|
||||||
<string name="frame_generation_supported">Поддерживается</string>
|
|
||||||
<string name="frame_generation_unsupported">Не поддерживается (нет модели памяти Vulkan)</string>
|
|
||||||
<string name="lossless_scaling_description">Предоставьте свою копию Lossless.dll для включения генерации кадров</string>
|
|
||||||
<string name="lossless_scaling_installed">Установлена</string>
|
|
||||||
<string name="lossless_scaling_not_installed">Не установлена</string>
|
|
||||||
<string name="lossless_scaling_replace">Заменить</string>
|
|
||||||
<string name="lossless_scaling_remove">Удалить</string>
|
|
||||||
<string name="lossless_scaling_remove_description">Удалить установленный Lossless.dll и его подготовленные шейдеры</string>
|
|
||||||
<string name="lossless_scaling_remove_confirmation">Генерация кадров перестанет работать, пока вы снова не установите Lossless.dll. Ваш исходный файл не пострадает.</string>
|
|
||||||
<string name="lossless_scaling_missing">Lossless.dll не установлен</string>
|
|
||||||
<string name="lossless_scaling_missing_description">Установите его через Настройки › Lossless Scaling для использования генерации кадров.</string>
|
|
||||||
<string name="lossless_scaling_locked">Сначала закройте игру</string>
|
|
||||||
<string name="lossless_scaling_locked_description">Lossless.dll нельзя изменить, пока запущена игра.</string>
|
|
||||||
<string name="lossless_scaling_remove_unavailable">Нечего удалять.</string>
|
|
||||||
<string name="lossless_scaling_remove_unavailable_description">Lossless.dll ещё не установлен.</string>
|
|
||||||
<string name="lossless_scaling_installing">Подготовка шейдеров генерации кадров…</string>
|
|
||||||
<string name="lossless_scaling_install_success">Lossless.dll успешно установлен</string>
|
|
||||||
<string name="lossless_scaling_install_failed">Не удалось установить Lossless.dll</string>
|
|
||||||
<string name="error_lossless_copy_failed">Не удалось скопировать выбранный файл.</string>
|
|
||||||
<string name="error_lossless_unreadable">Не удалось прочитать выбранный файл.</string>
|
|
||||||
<string name="error_lossless_not_pe">Выбранный файл не является библиотекой Windows. Выберите Lossless.dll из установки Lossless Scaling.</string>
|
|
||||||
<string name="error_lossless_missing_shaders">Эта копия Lossless.dll не содержит шейдеров генерации кадров. Обновите Lossless Scaling и попробуйте снова.</string>
|
|
||||||
<string name="error_lossless_translation_failed">Не удалось транслировать шейдеры генерации кадров. Эта версия Lossless Scaling пока не поддерживается.</string>
|
|
||||||
<string name="error_lossless_cache_failed">Не удалось записать транслированные шейдеры в хранилище. Проверьте, есть ли свободное место.</string>
|
|
||||||
<string name="advanced_settings">Расширенные настройки</string>
|
<string name="advanced_settings">Расширенные настройки</string>
|
||||||
<string name="settings_description">Настройка параметров эмулятора</string>
|
<string name="settings_description">Настройка параметров эмулятора</string>
|
||||||
<string name="search_recently_played">Недавно сыгранные</string>
|
<string name="search_recently_played">Недавно сыгранные</string>
|
||||||
@@ -491,9 +439,6 @@
|
|||||||
<string name="use_custom_rtc_description">Позволяет установить пользовательские часы реального времени отдельно от текущего системного времени.</string>
|
<string name="use_custom_rtc_description">Позволяет установить пользовательские часы реального времени отдельно от текущего системного времени.</string>
|
||||||
<string name="set_custom_rtc">Установить пользовательский RTC</string>
|
<string name="set_custom_rtc">Установить пользовательский RTC</string>
|
||||||
|
|
||||||
<!-- CPU -->
|
|
||||||
<string name="fast_cpu_time">Тактовая частота ЦП</string>
|
|
||||||
<string name="fast_cpu_time_description">Повышает тактовую частоту, которую сообщает эмулируемый процессор, что убирает некоторые ограничители FPS. На более слабых процессорах производительность может снизиться, а в некоторых играх возможно некорректное поведение.</string>
|
|
||||||
<string name="custom_cpu_ticks">Пользовательские такты ЦП</string>
|
<string name="custom_cpu_ticks">Пользовательские такты ЦП</string>
|
||||||
<string name="custom_cpu_ticks_description">Установите пользовательское значение тактов ЦП. Более высокие значения могут увеличить производительность, но также могут вызвать зависание игры. Рекомендуется диапазон 77–21000.</string>
|
<string name="custom_cpu_ticks_description">Установите пользовательское значение тактов ЦП. Более высокие значения могут увеличить производительность, но также могут вызвать зависание игры. Рекомендуется диапазон 77–21000.</string>
|
||||||
<string name="cpu_ticks">Такты</string>
|
<string name="cpu_ticks">Такты</string>
|
||||||
@@ -554,8 +499,6 @@
|
|||||||
|
|
||||||
<string name="hacks">Хаки</string>
|
<string name="hacks">Хаки</string>
|
||||||
|
|
||||||
<string name="fast_gpu_time">Тактовая частота ГПУ</string>
|
|
||||||
<string name="fast_gpu_time_description">Заставляет игру думать, что работа ГПУ завершается быстрее, чем на самом деле, поэтому она перестаёт снижать разрешение и дистанцию прорисовки, чтобы подстраиваться под тактовые частоты Switch.</string>
|
|
||||||
<string name="skip_cpu_inner_invalidation">Пропустить внутреннюю инвалидацию ЦП</string>
|
<string name="skip_cpu_inner_invalidation">Пропустить внутреннюю инвалидацию ЦП</string>
|
||||||
<string name="skip_cpu_inner_invalidation_description">Пропускает некоторые инвалидации кэша на стороне ЦП при обновлениях памяти, уменьшая нагрузку на процессор и повышая производительность. Может вызывать сбои в некоторых играх.</string>
|
<string name="skip_cpu_inner_invalidation_description">Пропускает некоторые инвалидации кэша на стороне ЦП при обновлениях памяти, уменьшая нагрузку на процессор и повышая производительность. Может вызывать сбои в некоторых играх.</string>
|
||||||
<string name="fix_bloom_effects">Исправить эффекты размытия</string>
|
<string name="fix_bloom_effects">Исправить эффекты размытия</string>
|
||||||
@@ -602,7 +545,6 @@
|
|||||||
|
|
||||||
<!-- Debug settings strings -->
|
<!-- Debug settings strings -->
|
||||||
<string name="cpu">ЦП</string>
|
<string name="cpu">ЦП</string>
|
||||||
<string name="clocks">Тактовая частота</string>
|
|
||||||
<string name="use_auto_stub">Использовать Auto Stub</string>
|
<string name="use_auto_stub">Использовать Auto Stub</string>
|
||||||
<string name="use_auto_stub_description">Автоматически заглушает отсутствующие сервисы и функции. Может улучшить совместимость, но вызывать сбои и проблемы стабильности.</string>
|
<string name="use_auto_stub_description">Автоматически заглушает отсутствующие сервисы и функции. Может улучшить совместимость, но вызывать сбои и проблемы стабильности.</string>
|
||||||
|
|
||||||
@@ -617,6 +559,7 @@
|
|||||||
<string name="log">Логирование</string>
|
<string name="log">Логирование</string>
|
||||||
<string name="flush_by_line">Сбрасывать логи отладки построчно</string>
|
<string name="flush_by_line">Сбрасывать логи отладки построчно</string>
|
||||||
<string name="flush_by_line_description">Сбрасывает логи отладки после каждой написанной строки, упрощая отладку в случае сбоев или зависаний.</string>
|
<string name="flush_by_line_description">Сбрасывает логи отладки после каждой написанной строки, упрощая отладку в случае сбоев или зависаний.</string>
|
||||||
|
|
||||||
<!-- GPU Logging strings -->
|
<!-- GPU Logging strings -->
|
||||||
<string name="gpu_logging_header">Ведение журнала ГПУ</string>
|
<string name="gpu_logging_header">Ведение журнала ГПУ</string>
|
||||||
<string name="gpu_log_level">Уровень журналирования</string>
|
<string name="gpu_log_level">Уровень журналирования</string>
|
||||||
@@ -1001,16 +944,6 @@
|
|||||||
<string name="memory_6gb">6 ГБ (Небезопасно)</string>
|
<string name="memory_6gb">6 ГБ (Небезопасно)</string>
|
||||||
<string name="memory_8gb">8 ГБ (Небезопасно)</string>
|
<string name="memory_8gb">8 ГБ (Небезопасно)</string>
|
||||||
|
|
||||||
<!-- CPU clock levels -->
|
|
||||||
<string name="clock_normal">Обычная</string>
|
|
||||||
<string name="clock_boost">Турбо</string>
|
|
||||||
<string name="clock_fast">Разгон</string>
|
|
||||||
|
|
||||||
<!-- GPU clock levels -->
|
|
||||||
<string name="fast_gpu_normal">Обычная</string>
|
|
||||||
<string name="fast_gpu_medium">Турбо</string>
|
|
||||||
<string name="fast_gpu_high">Разгон</string>
|
|
||||||
|
|
||||||
<!-- GPU swizzle texture size -->
|
<!-- GPU swizzle texture size -->
|
||||||
<string name="gpu_texturesizeswizzle_verysmall">Очень малый (16 МБ)</string>
|
<string name="gpu_texturesizeswizzle_verysmall">Очень малый (16 МБ)</string>
|
||||||
<string name="gpu_texturesizeswizzle_small">Малый (32 МБ)</string>
|
<string name="gpu_texturesizeswizzle_small">Малый (32 МБ)</string>
|
||||||
@@ -1138,6 +1071,7 @@
|
|||||||
<string name="theme_mode_light">Светлая</string>
|
<string name="theme_mode_light">Светлая</string>
|
||||||
<string name="theme_mode_dark">Темная</string>
|
<string name="theme_mode_dark">Темная</string>
|
||||||
|
|
||||||
|
|
||||||
<!-- Black backgrounds theme -->
|
<!-- Black backgrounds theme -->
|
||||||
<string name="use_black_backgrounds">Чёрный фон</string>
|
<string name="use_black_backgrounds">Чёрный фон</string>
|
||||||
<string name="use_black_backgrounds_description">При использовании темной темы применяйте черный фон.</string>
|
<string name="use_black_backgrounds_description">При использовании темной темы применяйте черный фон.</string>
|
||||||
|
|||||||
@@ -60,6 +60,7 @@
|
|||||||
<string name="cpuopt_unsafe_host_mmu_description">Ова оптимизација убрзава приступ меморији од стране гостујућег програма. Укључивање изазива да се читања/уписа меморије госта обављају директно у меморији и користе MMU домаћина. Искључивање присиљава све приступе меморији да користе софтверску емулацију MMU.</string>
|
<string name="cpuopt_unsafe_host_mmu_description">Ова оптимизација убрзава приступ меморији од стране гостујућег програма. Укључивање изазива да се читања/уписа меморије госта обављају директно у меморији и користе MMU домаћина. Искључивање присиљава све приступе меморији да користе софтверску емулацију MMU.</string>
|
||||||
<!-- NVDEC Emulation -->
|
<!-- NVDEC Emulation -->
|
||||||
<string name="nvdec_emulation">НВДЕЦ Емулација</string>
|
<string name="nvdec_emulation">НВДЕЦ Емулација</string>
|
||||||
|
<string name="nvdec_emulation_description">Изаберите како се видео декодирање (НВДЕЦ) обрађује током секс и увозних интросија.</string>
|
||||||
<string name="nvdec_emulation_none">Ниједан</string>
|
<string name="nvdec_emulation_none">Ниједан</string>
|
||||||
|
|
||||||
<!-- Optimize SPIRV output -->
|
<!-- Optimize SPIRV output -->
|
||||||
@@ -400,6 +401,7 @@
|
|||||||
<string name="log">Сечеља</string>
|
<string name="log">Сечеља</string>
|
||||||
<string name="flush_by_line">Записници за уклањање погрешака по линији</string>
|
<string name="flush_by_line">Записници за уклањање погрешака по линији</string>
|
||||||
<string name="flush_by_line_description">Испушта ознаке за уклањање погрешака на сваком писменом линијском линији, олакшавање уклањања погрешака у случајевима пада или замрзавања.</string>
|
<string name="flush_by_line_description">Испушта ознаке за уклањање погрешака на сваком писменом линијском линији, олакшавање уклањања погрешака у случајевима пада или замрзавања.</string>
|
||||||
|
|
||||||
<!-- Audio settings strings -->
|
<!-- Audio settings strings -->
|
||||||
<string name="audio_output_engine">Излазни мотор</string>
|
<string name="audio_output_engine">Излазни мотор</string>
|
||||||
<string name="audio_volume">Запремина</string>
|
<string name="audio_volume">Запремина</string>
|
||||||
|
|||||||
@@ -106,6 +106,7 @@
|
|||||||
|
|
||||||
<!-- NVDEC Emulation -->
|
<!-- NVDEC Emulation -->
|
||||||
<string name="nvdec_emulation">Емуляція NVDEC</string>
|
<string name="nvdec_emulation">Емуляція NVDEC</string>
|
||||||
|
<string name="nvdec_emulation_description">Обробка відео під час катсцен</string>
|
||||||
<string name="nvdec_emulation_none">Вимкнено</string>
|
<string name="nvdec_emulation_none">Вимкнено</string>
|
||||||
|
|
||||||
<!-- Optimize SPIRV output -->
|
<!-- Optimize SPIRV output -->
|
||||||
@@ -553,6 +554,7 @@
|
|||||||
<string name="log">Журналювання</string>
|
<string name="log">Журналювання</string>
|
||||||
<string name="flush_by_line">Скидати логи налагодження по рядках</string>
|
<string name="flush_by_line">Скидати логи налагодження по рядках</string>
|
||||||
<string name="flush_by_line_description">Скидає логи налагодження після кожного написаного рядка, полегшуючи налагодження у випадках збоїв або зависань.</string>
|
<string name="flush_by_line_description">Скидає логи налагодження після кожного написаного рядка, полегшуючи налагодження у випадках збоїв або зависань.</string>
|
||||||
|
|
||||||
<!-- GPU Logging strings -->
|
<!-- GPU Logging strings -->
|
||||||
<string name="gpu_logging_header">Журналювання ГП</string>
|
<string name="gpu_logging_header">Журналювання ГП</string>
|
||||||
<string name="gpu_log_level">Рівень журналювання</string>
|
<string name="gpu_log_level">Рівень журналювання</string>
|
||||||
@@ -1051,6 +1053,7 @@
|
|||||||
<string name="theme_mode_light">Світла</string>
|
<string name="theme_mode_light">Світла</string>
|
||||||
<string name="theme_mode_dark">Темна</string>
|
<string name="theme_mode_dark">Темна</string>
|
||||||
|
|
||||||
|
|
||||||
<!-- Black backgrounds theme -->
|
<!-- Black backgrounds theme -->
|
||||||
<string name="use_black_backgrounds">Чорний фон</string>
|
<string name="use_black_backgrounds">Чорний фон</string>
|
||||||
<string name="use_black_backgrounds_description">Використовувати чорний фон у темній темі.</string>
|
<string name="use_black_backgrounds_description">Використовувати чорний фон у темній темі.</string>
|
||||||
|
|||||||
@@ -62,6 +62,7 @@
|
|||||||
<string name="cpuopt_unsafe_host_mmu_description">Tối ưu hóa này tăng tốc độ truy cập bộ nhớ của chương trình khách. Bật nó lên khiến các thao tác đọc/ghi bộ nhớ khách được thực hiện trực tiếp vào bộ nhớ và sử dụng MMU của Máy chủ. Tắt tính năng này buộc tất cả quyền truy cập bộ nhớ phải sử dụng Giả lập MMU Phần mềm.</string>
|
<string name="cpuopt_unsafe_host_mmu_description">Tối ưu hóa này tăng tốc độ truy cập bộ nhớ của chương trình khách. Bật nó lên khiến các thao tác đọc/ghi bộ nhớ khách được thực hiện trực tiếp vào bộ nhớ và sử dụng MMU của Máy chủ. Tắt tính năng này buộc tất cả quyền truy cập bộ nhớ phải sử dụng Giả lập MMU Phần mềm.</string>
|
||||||
<!-- NVDEC Emulation -->
|
<!-- NVDEC Emulation -->
|
||||||
<string name="nvdec_emulation">Giả lập NVDEC</string>
|
<string name="nvdec_emulation">Giả lập NVDEC</string>
|
||||||
|
<string name="nvdec_emulation_description">Chọn cách xử lý giải mã video</string>
|
||||||
<string name="nvdec_emulation_none">Tắt</string>
|
<string name="nvdec_emulation_none">Tắt</string>
|
||||||
|
|
||||||
<!-- Optimize SPIRV output -->
|
<!-- Optimize SPIRV output -->
|
||||||
@@ -372,6 +373,7 @@
|
|||||||
<string name="log">Ghi nhật ký</string>
|
<string name="log">Ghi nhật ký</string>
|
||||||
<string name="flush_by_line">Xả nhật ký gỡ lỗi theo dòng</string>
|
<string name="flush_by_line">Xả nhật ký gỡ lỗi theo dòng</string>
|
||||||
<string name="flush_by_line_description">Xả nhật ký gỡ lỗi trên mỗi dòng được viết, giúp gỡ lỗi dễ dàng hơn trong trường hợp bị treo hoặc sập.</string>
|
<string name="flush_by_line_description">Xả nhật ký gỡ lỗi trên mỗi dòng được viết, giúp gỡ lỗi dễ dàng hơn trong trường hợp bị treo hoặc sập.</string>
|
||||||
|
|
||||||
<!-- Audio settings strings -->
|
<!-- Audio settings strings -->
|
||||||
<string name="audio_output_engine">Công cụ xuất âm thanh</string>
|
<string name="audio_output_engine">Công cụ xuất âm thanh</string>
|
||||||
<string name="audio_volume">Âm lượng</string>
|
<string name="audio_volume">Âm lượng</string>
|
||||||
|
|||||||
@@ -106,7 +106,7 @@
|
|||||||
|
|
||||||
<!-- NVDEC Emulation -->
|
<!-- NVDEC Emulation -->
|
||||||
<string name="nvdec_emulation">NVDEC模拟</string>
|
<string name="nvdec_emulation">NVDEC模拟</string>
|
||||||
<string name="nvdec_emulation_description">如果在过场动画中出现崩溃就切换为 CPU。</string>
|
<string name="nvdec_emulation_description">播放过场与开场动画期间的视频解码处理方式(NVDEC)。</string>
|
||||||
<string name="nvdec_emulation_none">禁用</string>
|
<string name="nvdec_emulation_none">禁用</string>
|
||||||
|
|
||||||
<!-- Optimize SPIRV output -->
|
<!-- Optimize SPIRV output -->
|
||||||
@@ -291,67 +291,6 @@
|
|||||||
<string name="gpu_driver_fetcher">GPU驱动获取器</string>
|
<string name="gpu_driver_fetcher">GPU驱动获取器</string>
|
||||||
<string name="gpu_driver_manager">GPU 驱动管理器</string>
|
<string name="gpu_driver_manager">GPU 驱动管理器</string>
|
||||||
<string name="install_gpu_driver_description">安装替代的驱动程序以获得更好的性能和精度</string>
|
<string name="install_gpu_driver_description">安装替代的驱动程序以获得更好的性能和精度</string>
|
||||||
<string name="frame_gen">帧生成</string>
|
|
||||||
<string name="frame_gen_per_game_description">配置针对此游戏的帧生成设定</string>
|
|
||||||
<string name="frame_gen_description">设定要在使用无损缩放渲染的帧之间应用的插帧。启用后强制采用FIFO呈现模式 。</string>
|
|
||||||
<string name="frame_gen_multiplier">多帧生成</string>
|
|
||||||
<string name="frame_gen_multiplier_description">对于每个渲染帧,设定应显示的帧。数值越高,所消耗的 GPU 时间就越会成倍增多。如果设定超过显示器能力的帧数,将会降低模拟速度。</string>
|
|
||||||
<string name="frame_gen_multiplier_2x">2x</string>
|
|
||||||
<string name="frame_gen_multiplier_3x">3x</string>
|
|
||||||
<string name="frame_gen_multiplier_4x">4x</string>
|
|
||||||
<string name="frame_gen_target_rate">目标帧率</string>
|
|
||||||
<string name="frame_gen_target_rate_description">选取一个符合显示器实际能能力的帧率。增幅会自动调整以保持设定的帧率不变,并回调任何会导致游戏运行变慢的设定。</string>
|
|
||||||
<string name="frame_gen_target_rate_off">使用固定增幅</string>
|
|
||||||
<string name="frame_gen_target_rate_60">60 FPS</string>
|
|
||||||
<string name="frame_gen_target_rate_90">90 FPS</string>
|
|
||||||
<string name="frame_gen_target_rate_120">120 FPS</string>
|
|
||||||
<string name="frame_gen_target_rate_144">144 FPS</string>
|
|
||||||
<string name="frame_gen_target_rate_165">165 FPS</string>
|
|
||||||
<string name="frame_gen_queue_target">帧队列目标</string>
|
|
||||||
<string name="frame_gen_queue_target_description">在显示之前有多少已完成渲染的帧正在等待。较大的队列可以缓解 GPU 突发的压力,但会增加输入延迟。</string>
|
|
||||||
<string name="frame_gen_queue_target_0">最低延迟 (无缓冲)</string>
|
|
||||||
<string name="frame_gen_queue_target_1">平衡 (1 帧)</string>
|
|
||||||
<string name="frame_gen_queue_target_2">最平滑 (2 帧)</string>
|
|
||||||
<string name="frame_gen_flow_scale_auto">将运动预估与游戏匹配</string>
|
|
||||||
<string name="frame_gen_flow_scale_auto_description">在游戏实际渲染的分辨率下估算运动,而不是在放大后的输出上。不会影响精确性,因为放大并不会增加运动细节。</string>
|
|
||||||
<string name="frame_gen_flow_scale">运动预估分辨率</string>
|
|
||||||
<string name="frame_gen_flow_scale_description">光流通道的分辨率,以输出的比例表示。降低它是提升性能最经济的做法。</string>
|
|
||||||
<string name="frame_gen_fp16">半精度着色器</string>
|
|
||||||
<string name="frame_gen_fp16_description">使用 16 位着色器变体。如果驱动或文件不支持会自动回退。</string>
|
|
||||||
<string name="frame_gen_dump_flow">转储已生成的帧</string>
|
|
||||||
<string name="frame_gen_dump_flow_description">为了排查问题,把光流 mip 级别和插值帧写入 lossless/debug 文件夹一次</string>
|
|
||||||
<string name="frame_gen_unsupported">帧生成不可用</string>
|
|
||||||
<string name="frame_gen_unsupported_description">这个 GPU 驱动不支持无损缩放着色器所需的 Vulkan 内存模型。</string>
|
|
||||||
<string name="lossless_scaling_setup_description">作为可选项。请提供您自己的 Lossless.dll 以便在之后可以启用帧生成。</string>
|
|
||||||
<string name="lossless_scaling_install">安装 Lossless.dll</string>
|
|
||||||
<string name="lossless_scaling_install_description">帧生成需要您自己从 Lossless Scaling 获得合法的 Lossless.dll 副本</string>
|
|
||||||
<string name="lossless_scaling_replace_description">选择其它 Lossless.dll 副本</string>
|
|
||||||
<string name="frame_generation_support">帧生成</string>
|
|
||||||
<string name="frame_generation_supported">支持</string>
|
|
||||||
<string name="frame_generation_unsupported">不支持 (无 Vulkan 内存模型)</string>
|
|
||||||
<string name="lossless_scaling">无损缩放</string>
|
|
||||||
<string name="lossless_scaling_description">提供您自己的 Lossless.dll 文件以启用帧生成</string>
|
|
||||||
<string name="lossless_scaling_installed">已安装</string>
|
|
||||||
<string name="lossless_scaling_not_installed">未安装</string>
|
|
||||||
<string name="lossless_scaling_replace">替换</string>
|
|
||||||
<string name="lossless_scaling_remove">移除</string>
|
|
||||||
<string name="lossless_scaling_remove_description">删除已安装的 Lossless.dll 及其准备好的着色器</string>
|
|
||||||
<string name="lossless_scaling_remove_confirmation">帧生成将停止工作,直到您重新安装 Lossless.dll。您的原始文件不会受到影响。</string>
|
|
||||||
<string name="lossless_scaling_missing">未安装 Lossless.dll</string>
|
|
||||||
<string name="lossless_scaling_missing_description">请从设置 › 无损缩放安装它以使用帧生成。</string>
|
|
||||||
<string name="lossless_scaling_locked">请先关闭游戏</string>
|
|
||||||
<string name="lossless_scaling_locked_description">无法在游戏运行时更改 Lossless.dll。</string>
|
|
||||||
<string name="lossless_scaling_remove_unavailable">没有可以移除的项目</string>
|
|
||||||
<string name="lossless_scaling_remove_unavailable_description">尚未安装 Lossless.dll。</string>
|
|
||||||
<string name="lossless_scaling_installing">正在准备帧生成着色器...</string>
|
|
||||||
<string name="lossless_scaling_install_success">已成功安装 Lossless.dll</string>
|
|
||||||
<string name="lossless_scaling_install_failed">无法安装 Lossless.dll </string>
|
|
||||||
<string name="error_lossless_copy_failed">无法复制选定的文件。</string>
|
|
||||||
<string name="error_lossless_unreadable">无法读取选定的文件。</string>
|
|
||||||
<string name="error_lossless_not_pe">选定的文件不是一个 Windows 动态链接库。请从您的 Lossless Scaling 安装目录中选择 Lossless.dll。</string>
|
|
||||||
<string name="error_lossless_missing_shaders">此副本的 Lossless.dll 中尚未包含帧生成着色器。请更新 Lossless Scaling 然后重试。</string>
|
|
||||||
<string name="error_lossless_translation_failed">无法翻译帧生成着色器。尚未支持此版本的 Lossless Scaling。</string>
|
|
||||||
<string name="error_lossless_cache_failed">已翻译的着色器无法写入到存储中。请确认其是否拥有足够的可用空间。</string>
|
|
||||||
<string name="advanced_settings">高级设置</string>
|
<string name="advanced_settings">高级设置</string>
|
||||||
<string name="settings_description">更改模拟器设置</string>
|
<string name="settings_description">更改模拟器设置</string>
|
||||||
<string name="search_recently_played">最近游玩</string>
|
<string name="search_recently_played">最近游玩</string>
|
||||||
@@ -620,6 +559,7 @@
|
|||||||
<string name="log">日志记录</string>
|
<string name="log">日志记录</string>
|
||||||
<string name="flush_by_line">按行刷新调试日志</string>
|
<string name="flush_by_line">按行刷新调试日志</string>
|
||||||
<string name="flush_by_line_description">在每行写入时刷新调试日志,使在崩溃或冻结时调试更容易。</string>
|
<string name="flush_by_line_description">在每行写入时刷新调试日志,使在崩溃或冻结时调试更容易。</string>
|
||||||
|
|
||||||
<!-- GPU Logging strings -->
|
<!-- GPU Logging strings -->
|
||||||
<string name="gpu_logging_header">GPU 日志</string>
|
<string name="gpu_logging_header">GPU 日志</string>
|
||||||
<string name="gpu_log_level">日志等级</string>
|
<string name="gpu_log_level">日志等级</string>
|
||||||
@@ -1141,6 +1081,7 @@
|
|||||||
<string name="theme_mode_light">浅色</string>
|
<string name="theme_mode_light">浅色</string>
|
||||||
<string name="theme_mode_dark">深色</string>
|
<string name="theme_mode_dark">深色</string>
|
||||||
|
|
||||||
|
|
||||||
<!-- Black backgrounds theme -->
|
<!-- Black backgrounds theme -->
|
||||||
<string name="use_black_backgrounds">使用黑色背景</string>
|
<string name="use_black_backgrounds">使用黑色背景</string>
|
||||||
<string name="use_black_backgrounds_description">使用深色主题时,套用黑色背景。</string>
|
<string name="use_black_backgrounds_description">使用深色主题时,套用黑色背景。</string>
|
||||||
|
|||||||
@@ -106,7 +106,7 @@
|
|||||||
|
|
||||||
<!-- NVDEC Emulation -->
|
<!-- NVDEC Emulation -->
|
||||||
<string name="nvdec_emulation">NVDEC模擬</string>
|
<string name="nvdec_emulation">NVDEC模擬</string>
|
||||||
<string name="nvdec_emulation_description">若在過場動畫中當機請切換成 CPU</string>
|
<string name="nvdec_emulation_description">選擇影片解碼(NVDEC)的方式</string>
|
||||||
<string name="nvdec_emulation_none">無</string>
|
<string name="nvdec_emulation_none">無</string>
|
||||||
|
|
||||||
<!-- Optimize SPIRV output -->
|
<!-- Optimize SPIRV output -->
|
||||||
@@ -182,7 +182,7 @@
|
|||||||
<string name="multiplayer_hide_empty_rooms">隱藏空房間</string>
|
<string name="multiplayer_hide_empty_rooms">隱藏空房間</string>
|
||||||
<string name="multiplayer_tap_refresh_to_check_again">點擊重新整理以重試</string>
|
<string name="multiplayer_tap_refresh_to_check_again">點擊重新整理以重試</string>
|
||||||
<string name="multiplayer_search_public_lobbies">搜尋房間…</string>
|
<string name="multiplayer_search_public_lobbies">搜尋房間…</string>
|
||||||
<string name="multiplayer_preferred_game_name">遊戲</string>
|
<string name="multiplayer_preferred_game_name">首選遊戲</string>
|
||||||
<string name="multiplayer_lobby_type">大廳類型</string>
|
<string name="multiplayer_lobby_type">大廳類型</string>
|
||||||
<string name="multiplayer_room_name_error">長度需為3-20個字元</string>
|
<string name="multiplayer_room_name_error">長度需為3-20個字元</string>
|
||||||
<string name="multiplayer_required">必填</string>
|
<string name="multiplayer_required">必填</string>
|
||||||
@@ -237,11 +237,11 @@
|
|||||||
<string name="update_install_failed">更新安裝失敗:%1$s</string>
|
<string name="update_install_failed">更新安裝失敗:%1$s</string>
|
||||||
<string name="home_search">搜尋</string>
|
<string name="home_search">搜尋</string>
|
||||||
<string name="home_settings">設定</string>
|
<string name="home_settings">設定</string>
|
||||||
<string name="empty_gamelist">找不到檔案,或者尚未選取遊戲目錄</string>
|
<string name="empty_gamelist">找不到檔案,或者尚未選取遊戲目錄。</string>
|
||||||
<string name="manage_game_folders">管理遊戲資料夾</string>
|
<string name="manage_game_folders">管理遊戲資料夾</string>
|
||||||
<string name="select_games_folder_description">允許 Eden 尋找您的遊戲檔案</string>
|
<string name="select_games_folder_description">允許 Eden 尋找您的遊戲檔案</string>
|
||||||
<string name="add_games_warning">跳過選擇遊戲資料夾?</string>
|
<string name="add_games_warning">跳過選擇遊戲資料夾?</string>
|
||||||
<string name="add_games_warning_description">如果未選擇遊戲資料夾,遊戲將不會顯示在遊戲清單</string>
|
<string name="add_games_warning_description">如果未選擇遊戲資料夾,遊戲將不會顯示在遊戲清單。</string>
|
||||||
<string name="add_games_warning_help">https://yuzu-mirror.github.io/help/quickstart/#dumping-games</string>
|
<string name="add_games_warning_help">https://yuzu-mirror.github.io/help/quickstart/#dumping-games</string>
|
||||||
<string name="home_search_games">搜尋遊戲</string>
|
<string name="home_search_games">搜尋遊戲</string>
|
||||||
<string name="search_settings">搜尋設定</string>
|
<string name="search_settings">搜尋設定</string>
|
||||||
@@ -291,38 +291,6 @@
|
|||||||
<string name="gpu_driver_fetcher">GPU驅動程式下載器</string>
|
<string name="gpu_driver_fetcher">GPU驅動程式下載器</string>
|
||||||
<string name="gpu_driver_manager">GPU 驅動程式管理員</string>
|
<string name="gpu_driver_manager">GPU 驅動程式管理員</string>
|
||||||
<string name="install_gpu_driver_description">安裝替代驅動程式以取得潛在的更佳效能或準確度</string>
|
<string name="install_gpu_driver_description">安裝替代驅動程式以取得潛在的更佳效能或準確度</string>
|
||||||
<string name="frame_gen">影格生成</string>
|
|
||||||
<string name="frame_gen_per_game_description">調整此遊戲的影格生成設定</string>
|
|
||||||
<string name="frame_gen_description">使用 Lossless Scaling 在已渲染的影格之間插入補間影格。啟用此功能時,會強制採用 FIFO 垂直同步</string>
|
|
||||||
<string name="frame_gen_multiplier">影格倍率</string>
|
|
||||||
<string name="frame_gen_multiplier_description">設定在每個已渲染的影格中要顯示的影格數。數值越高所需的 GPU 運算時間也會按比例增加。若要求的影格數超過裝置顯示器能呈現的數量將會降低模擬速度</string>
|
|
||||||
<string name="frame_gen_multiplier_2x">2x</string>
|
|
||||||
<string name="frame_gen_multiplier_3x">3x</string>
|
|
||||||
<string name="frame_gen_multiplier_4x">4x</string>
|
|
||||||
<string name="frame_gen_target_rate">目標影格率</string>
|
|
||||||
<string name="frame_gen_target_rate_description">選擇裝置顯示器能實際呈現的影格率。之後倍率器會自動升高或降低以維持影格率。如果某個調整導致遊戲本身運作變慢,則會自動復原該設定</string>
|
|
||||||
<string name="frame_gen_target_rate_off">使用固定倍率</string>
|
|
||||||
<string name="frame_gen_target_rate_60">60 FPS</string>
|
|
||||||
<string name="frame_gen_target_rate_90">90 FPS</string>
|
|
||||||
<string name="frame_gen_target_rate_120">120 FPS</string>
|
|
||||||
<string name="frame_gen_target_rate_144">144 FPS</string>
|
|
||||||
<string name="frame_gen_target_rate_165">165 FPS</string>
|
|
||||||
<string name="frame_gen_queue_target">影格佇列目標</string>
|
|
||||||
<string name="frame_gen_queue_target_description">最多允許多少個已完成的影格在顯示器前等待,較大的佇列可以吸收 GPU 突發負載,但會增加輸入延遲</string>
|
|
||||||
<string name="frame_gen_queue_target_0">最低延遲(無緩衝)</string>
|
|
||||||
<string name="frame_gen_queue_target_1">平衡(1影格)</string>
|
|
||||||
<string name="frame_gen_queue_target_2">最流暢(2影格)</string>
|
|
||||||
<string name="frame_gen_flow_scale_auto">配合遊戲調整運動預測</string>
|
|
||||||
<string name="frame_gen_flow_scale_auto_description">以遊戲實際渲染的解析度而非升頻後的輸出進行運動預測。由於升頻後不會增加任何動態細節,因此不會影響準確度</string>
|
|
||||||
<string name="frame_gen_flow_scale">運動預測解析度</string>
|
|
||||||
<string name="frame_gen_flow_scale_description">光流處理的解析度,以輸出解析度的比例表示。降低此設定值是減少效能負載最有效的方法</string>
|
|
||||||
<string name="frame_gen_fp16">半準確著色器</string>
|
|
||||||
<string name="frame_gen_fp16_description">使用16位元著色器。如果驅動程式或著色器檔案不支援則會自動切換成其它版本</string>
|
|
||||||
<string name="frame_gen_dump_flow">傾印生成的著色器</string>
|
|
||||||
<string name="frame_gen_dump_flow_description">將光流的 MIP 層級與補間影格寫入 Eden 資料夾中的 lossless\debug 資料夾以便進行疑難排解</string>
|
|
||||||
<string name="frame_gen_unsupported">無法使用影格生成</string>
|
|
||||||
<string name="frame_gen_unsupported_description">Lossless Scaling 的著色器需要 Vulkan 記憶體模型,所選的驅動程式不支援該功能</string>
|
|
||||||
<string name="lossless_scaling_setup_description">可選擇安裝自己擁有的 Lossless.dll 以在之後啟用影格生成功能</string>
|
|
||||||
<string name="advanced_settings">進階設定</string>
|
<string name="advanced_settings">進階設定</string>
|
||||||
<string name="settings_description">進行模擬器設定</string>
|
<string name="settings_description">進行模擬器設定</string>
|
||||||
<string name="search_recently_played">最近遊玩</string>
|
<string name="search_recently_played">最近遊玩</string>
|
||||||
@@ -591,6 +559,7 @@
|
|||||||
<string name="log">日誌</string>
|
<string name="log">日誌</string>
|
||||||
<string name="flush_by_line">按行寫入偵錯日誌</string>
|
<string name="flush_by_line">按行寫入偵錯日誌</string>
|
||||||
<string name="flush_by_line_description">在每行寫入時重新整理偵錯日誌,讓程式在當機或閃退時更容易偵錯。</string>
|
<string name="flush_by_line_description">在每行寫入時重新整理偵錯日誌,讓程式在當機或閃退時更容易偵錯。</string>
|
||||||
|
|
||||||
<!-- GPU Logging strings -->
|
<!-- GPU Logging strings -->
|
||||||
<string name="gpu_logging_header">GPU 日誌</string>
|
<string name="gpu_logging_header">GPU 日誌</string>
|
||||||
<string name="gpu_log_level">記錄層級</string>
|
<string name="gpu_log_level">記錄層級</string>
|
||||||
@@ -726,7 +695,7 @@
|
|||||||
<string name="import_complete">導入完成</string>
|
<string name="import_complete">導入完成</string>
|
||||||
<string name="use_global_setting">使用全域設定</string>
|
<string name="use_global_setting">使用全域設定</string>
|
||||||
<string name="operation_completed_successfully">操作已成功完成</string>
|
<string name="operation_completed_successfully">操作已成功完成</string>
|
||||||
<string name="confirm">確認</string>
|
<string name="confirm">下載</string>
|
||||||
<string name="load">載入</string>
|
<string name="load">載入</string>
|
||||||
<string name="save">儲存</string>
|
<string name="save">儲存</string>
|
||||||
|
|
||||||
@@ -899,7 +868,7 @@
|
|||||||
<string name="driver_missing_title">需要GPU驅動程式</string>
|
<string name="driver_missing_title">需要GPU驅動程式</string>
|
||||||
<string name="driver_missing_message">這個遊戲的設定需要 \"%s\"驅動程式,而它並沒有安裝在您的裝置上\n\n要下載並安裝此驅動程式嗎?</string>
|
<string name="driver_missing_message">這個遊戲的設定需要 \"%s\"驅動程式,而它並沒有安裝在您的裝置上\n\n要下載並安裝此驅動程式嗎?</string>
|
||||||
<string name="driver_download_cancelled">驅動程式下載已取消。沒有所需的驅動程式無法啟動遊戲。</string>
|
<string name="driver_download_cancelled">驅動程式下載已取消。沒有所需的驅動程式無法啟動遊戲。</string>
|
||||||
<string name="download">下載</string>
|
<string name="download">遷移</string>
|
||||||
|
|
||||||
<!-- Emulation Menu -->
|
<!-- Emulation Menu -->
|
||||||
<string name="emulation_exit">結束模擬</string>
|
<string name="emulation_exit">結束模擬</string>
|
||||||
@@ -1037,6 +1006,7 @@
|
|||||||
<string name="theme_mode_light">淺色</string>
|
<string name="theme_mode_light">淺色</string>
|
||||||
<string name="theme_mode_dark">深色</string>
|
<string name="theme_mode_dark">深色</string>
|
||||||
|
|
||||||
|
|
||||||
<!-- Black backgrounds theme -->
|
<!-- Black backgrounds theme -->
|
||||||
<string name="use_black_backgrounds">黑色背景</string>
|
<string name="use_black_backgrounds">黑色背景</string>
|
||||||
<string name="use_black_backgrounds_description">使用深色主題時,套用黑色背景。</string>
|
<string name="use_black_backgrounds_description">使用深色主題時,套用黑色背景。</string>
|
||||||
|
|||||||
@@ -636,8 +636,6 @@
|
|||||||
<string name="log">Logging</string>
|
<string name="log">Logging</string>
|
||||||
<string name="flush_by_line">Flush debug logs by line</string>
|
<string name="flush_by_line">Flush debug logs by line</string>
|
||||||
<string name="flush_by_line_description">Flushes debugging logs on each line written, making debugging easier in cases of crashing or freezing.</string>
|
<string name="flush_by_line_description">Flushes debugging logs on each line written, making debugging easier in cases of crashing or freezing.</string>
|
||||||
<string name="extended_logging">Enable extended logging</string>
|
|
||||||
<string name="extended_logging_description">Increases the maximum log file size from 100 MiB to 1 GiB.</string>
|
|
||||||
<string name="log_filter">Log filter</string>
|
<string name="log_filter">Log filter</string>
|
||||||
<string name="log_filter_description">Controls Eden\'s log categories. Example: *:Info Service.LM:Debug</string>
|
<string name="log_filter_description">Controls Eden\'s log categories. Example: *:Info Service.LM:Debug</string>
|
||||||
|
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ add_library(
|
|||||||
param_package.h
|
param_package.h
|
||||||
parent_of_member.h
|
parent_of_member.h
|
||||||
point.h
|
point.h
|
||||||
|
quaternion.h
|
||||||
range_map.h
|
range_map.h
|
||||||
range_mutex.h
|
range_mutex.h
|
||||||
range_sets.h
|
range_sets.h
|
||||||
|
|||||||
@@ -0,0 +1,79 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2016 Citra Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/vector_math.h"
|
||||||
|
|
||||||
|
namespace Common {
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class Quaternion {
|
||||||
|
public:
|
||||||
|
Vec3<T> xyz;
|
||||||
|
T w{};
|
||||||
|
|
||||||
|
[[nodiscard]] Quaternion<decltype(-T{})> Inverse() const {
|
||||||
|
return {-xyz, w};
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] Quaternion<decltype(T{} + T{})> operator+(const Quaternion& other) const {
|
||||||
|
return {xyz + other.xyz, w + other.w};
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] Quaternion<decltype(T{} - T{})> operator-(const Quaternion& other) const {
|
||||||
|
return {xyz - other.xyz, w - other.w};
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] Quaternion<decltype(T{} * T{} - T{} * T{})> operator*(
|
||||||
|
const Quaternion& other) const {
|
||||||
|
return {xyz * other.w + other.xyz * w + Cross(xyz, other.xyz),
|
||||||
|
w * other.w - Dot(xyz, other.xyz)};
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] Quaternion<T> Normalized() const {
|
||||||
|
T length = std::sqrt(xyz.Length2() + w * w);
|
||||||
|
return {xyz / length, w / length};
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] std::array<decltype(-T{}), 16> ToMatrix() const {
|
||||||
|
const T x2 = xyz[0] * xyz[0];
|
||||||
|
const T y2 = xyz[1] * xyz[1];
|
||||||
|
const T z2 = xyz[2] * xyz[2];
|
||||||
|
|
||||||
|
const T xy = xyz[0] * xyz[1];
|
||||||
|
const T wz = w * xyz[2];
|
||||||
|
const T xz = xyz[0] * xyz[2];
|
||||||
|
const T wy = w * xyz[1];
|
||||||
|
const T yz = xyz[1] * xyz[2];
|
||||||
|
const T wx = w * xyz[0];
|
||||||
|
|
||||||
|
return {1.0f - 2.0f * (y2 + z2),
|
||||||
|
2.0f * (xy + wz),
|
||||||
|
2.0f * (xz - wy),
|
||||||
|
0.0f,
|
||||||
|
2.0f * (xy - wz),
|
||||||
|
1.0f - 2.0f * (x2 + z2),
|
||||||
|
2.0f * (yz + wx),
|
||||||
|
0.0f,
|
||||||
|
2.0f * (xz + wy),
|
||||||
|
2.0f * (yz - wx),
|
||||||
|
1.0f - 2.0f * (x2 + y2),
|
||||||
|
0.0f,
|
||||||
|
0.0f,
|
||||||
|
0.0f,
|
||||||
|
0.0f,
|
||||||
|
1.0f};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
[[nodiscard]] auto QuaternionRotate(const Quaternion<T>& q, const Vec3<T>& v) {
|
||||||
|
return v + 2 * Cross(q.xyz, Cross(q.xyz, v) + v * q.w);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] inline Quaternion<float> MakeQuaternion(const Vec3<float>& axis, float angle) {
|
||||||
|
return {axis * std::sin(angle / 2), std::cos(angle / 2)};
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Common
|
||||||
@@ -858,7 +858,7 @@ struct Values {
|
|||||||
SwitchableSetting<std::string> program_args{linkage,
|
SwitchableSetting<std::string> program_args{linkage,
|
||||||
std::string(),
|
std::string(),
|
||||||
"program_args",
|
"program_args",
|
||||||
Category::Debugging,
|
Category::System,
|
||||||
Specialization::Default,
|
Specialization::Default,
|
||||||
true, // save_ - persist in config file
|
true, // save_ - persist in config file
|
||||||
false}; // runtime_modifiable_ - startup-only
|
false}; // runtime_modifiable_ - startup-only
|
||||||
@@ -904,7 +904,7 @@ struct Values {
|
|||||||
0,
|
0,
|
||||||
65535,
|
65535,
|
||||||
"debug_knobs",
|
"debug_knobs",
|
||||||
Category::Debugging,
|
Category::System,
|
||||||
Specialization::Countable,
|
Specialization::Countable,
|
||||||
true,
|
true,
|
||||||
true};
|
true};
|
||||||
|
|||||||
+717
-93
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: 2014 Tony Wasserka
|
// SPDX-FileCopyrightText: 2014 Tony Wasserka
|
||||||
@@ -7,128 +7,752 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __ARM_NEON
|
||||||
|
#include <arm_neon.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
namespace Common {
|
namespace Common {
|
||||||
|
|
||||||
template <typename T, size_t N>
|
template <typename T>
|
||||||
class Vec {
|
class Vec2;
|
||||||
|
template <typename T>
|
||||||
|
class Vec3;
|
||||||
|
template <typename T>
|
||||||
|
class Vec4;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class Vec2 {
|
||||||
public:
|
public:
|
||||||
std::array<T, N> elems{};
|
T x{};
|
||||||
|
T y{};
|
||||||
|
|
||||||
constexpr Vec() = default;
|
constexpr Vec2() = default;
|
||||||
constexpr Vec(T e0) noexcept : elems{e0} {}
|
constexpr Vec2(const T& x_, const T& y_) : x(x_), y(y_) {}
|
||||||
constexpr Vec(T e0, T e1) noexcept : elems{e0, e1} {}
|
|
||||||
constexpr Vec(T e0, T e1, T e2) noexcept : elems{e0, e1, e2} {}
|
|
||||||
constexpr Vec(T e0, T e1, T e2, T e4) noexcept : elems{e0, e1, e2, e4} {}
|
|
||||||
//explicit constexpr Vec(const std::initializer_list<T> elems_) noexcept : elems{elems_} {}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr Vec<decltype(T{} + T{}), N> operator+(const Vec o) const noexcept {
|
template <typename T2>
|
||||||
Vec<decltype(T{} + T{}), N> r{};
|
[[nodiscard]] constexpr Vec2<T2> Cast() const {
|
||||||
for (size_t i = 0; i < N; ++i)
|
return Vec2<T2>(static_cast<T2>(x), static_cast<T2>(y));
|
||||||
r.elems[i] = elems[i] + o.elems[i];
|
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
constexpr Vec<T, N> operator+=(const Vec<T, N> o) noexcept { return *this = *this + o; }
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr Vec<decltype(T{} - T{}), N> operator-(const Vec o) const noexcept {
|
[[nodiscard]] static constexpr Vec2 AssignToAll(const T& f) {
|
||||||
Vec<decltype(T{} - T{}), N> r{};
|
return Vec2{f, f};
|
||||||
for (size_t i = 0; i < N; ++i)
|
}
|
||||||
r.elems[i] = elems[i] - o.elems[i];
|
|
||||||
return r;
|
[[nodiscard]] constexpr Vec2<decltype(T{} + T{})> operator+(const Vec2& other) const {
|
||||||
|
return {x + other.x, y + other.y};
|
||||||
|
}
|
||||||
|
constexpr Vec2& operator+=(const Vec2& other) {
|
||||||
|
x += other.x;
|
||||||
|
y += other.y;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
[[nodiscard]] constexpr Vec2<decltype(T{} - T{})> operator-(const Vec2& other) const {
|
||||||
|
return {x - other.x, y - other.y};
|
||||||
|
}
|
||||||
|
constexpr Vec2& operator-=(const Vec2& other) {
|
||||||
|
x -= other.x;
|
||||||
|
y -= other.y;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
constexpr Vec<T, N> operator-=(const Vec<T, N> o) noexcept { return *this = *this - o; }
|
|
||||||
|
|
||||||
template <typename U = T>
|
template <typename U = T>
|
||||||
[[nodiscard]] constexpr Vec<std::enable_if_t<std::is_signed_v<U>, U>, N> operator-() const noexcept {
|
[[nodiscard]] constexpr Vec2<std::enable_if_t<std::is_signed_v<U>, U>> operator-() const {
|
||||||
Vec<U, N> r{};
|
return {-x, -y};
|
||||||
for (size_t i = 0; i < N; ++i)
|
}
|
||||||
r.elems[i] = -elems[i];
|
[[nodiscard]] constexpr Vec2<decltype(T{} * T{})> operator*(const Vec2& other) const {
|
||||||
return r;
|
return {x * other.x, y * other.y};
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] constexpr Vec<decltype(T{} * T{}), N> operator*(const Vec o) const noexcept {
|
|
||||||
Vec<decltype(T{} * T{}), N> r{};
|
|
||||||
for (size_t i = 0; i < N; ++i)
|
|
||||||
r.elems[i] = elems[i] * o.elems[i];
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
template <typename V>
|
template <typename V>
|
||||||
[[nodiscard]] constexpr Vec<decltype(T{} * V{}), N> operator*(const V f) const noexcept {
|
[[nodiscard]] constexpr Vec2<decltype(T{} * V{})> operator*(const V& f) const {
|
||||||
using TV = decltype(T{} * V{});
|
using TV = decltype(T{} * V{});
|
||||||
using C = std::common_type_t<T, V>;
|
using C = std::common_type_t<T, V>;
|
||||||
Vec<TV, N> r{};
|
|
||||||
for (size_t i = 0; i < N; ++i)
|
return {
|
||||||
r.elems[i] = TV(C(elems[i]) * C(f));
|
static_cast<TV>(static_cast<C>(x) * static_cast<C>(f)),
|
||||||
return r;
|
static_cast<TV>(static_cast<C>(y) * static_cast<C>(f)),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
template <typename V>
|
|
||||||
constexpr Vec<T, N> operator*=(const V f) noexcept { return *this = *this * f; }
|
|
||||||
|
|
||||||
template <typename V>
|
template <typename V>
|
||||||
[[nodiscard]] constexpr Vec<decltype(T{} / V{}), N> operator/(const V f) const noexcept {
|
constexpr Vec2& operator*=(const V& f) {
|
||||||
|
*this = *this * f;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename V>
|
||||||
|
[[nodiscard]] constexpr Vec2<decltype(T{} / V{})> operator/(const V& f) const {
|
||||||
using TV = decltype(T{} / V{});
|
using TV = decltype(T{} / V{});
|
||||||
using C = std::common_type_t<T, V>;
|
using C = std::common_type_t<T, V>;
|
||||||
Vec<TV, N> r{};
|
|
||||||
for (size_t i = 0; i < N; ++i)
|
|
||||||
r.elems[i] = TV(C(elems[i]) / C(f));
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
template <typename V>
|
|
||||||
constexpr Vec<T, N> operator/=(const V f) noexcept { return *this = *this / f; }
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr T Length2() const noexcept {
|
|
||||||
T r{};
|
|
||||||
for (size_t i = 0; i < N; ++i)
|
|
||||||
r += elems[i] * elems[i];
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
// Only implemented for T=float
|
|
||||||
[[nodiscard]] T Length() const { return T(std::sqrt(float(Length2()))); }
|
|
||||||
[[nodiscard]] Vec<T, N> Normalized() const { return *this / Length(); }
|
|
||||||
[[nodiscard]] constexpr T& operator[](std::size_t i) noexcept { return elems[i]; }
|
|
||||||
[[nodiscard]] constexpr const T& operator[](std::size_t i) const noexcept { return elems[i]; }
|
|
||||||
|
|
||||||
[[nodiscard]] std::array<decltype(-T{}), 16> ToMatrix() const {
|
|
||||||
const T x2 = elems[0] * elems[0];
|
|
||||||
const T y2 = elems[1] * elems[1];
|
|
||||||
const T z2 = elems[2] * elems[2];
|
|
||||||
|
|
||||||
const T xy = elems[0] * elems[1];
|
|
||||||
const T wz = elems[3] * elems[2];
|
|
||||||
const T xz = elems[0] * elems[2];
|
|
||||||
const T wy = elems[3] * elems[1];
|
|
||||||
const T yz = elems[1] * elems[2];
|
|
||||||
const T wx = elems[3] * elems[0];
|
|
||||||
return {
|
return {
|
||||||
1.0f - 2.0f * (y2 + z2),
|
static_cast<TV>(static_cast<C>(x) / static_cast<C>(f)),
|
||||||
2.0f * (xy + wz),
|
static_cast<TV>(static_cast<C>(y) / static_cast<C>(f)),
|
||||||
2.0f * (xz - wy),
|
|
||||||
0.0f,
|
|
||||||
2.0f * (xy - wz),
|
|
||||||
1.0f - 2.0f * (x2 + z2),
|
|
||||||
2.0f * (yz + wx),
|
|
||||||
0.0f,
|
|
||||||
2.0f * (xz + wy),
|
|
||||||
2.0f * (yz - wx),
|
|
||||||
1.0f - 2.0f * (x2 + y2),
|
|
||||||
0.0f,
|
|
||||||
0.0f,
|
|
||||||
0.0f,
|
|
||||||
0.0f,
|
|
||||||
1.0f
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename V>
|
||||||
|
constexpr Vec2& operator/=(const V& f) {
|
||||||
|
*this = *this / f;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr T Length2() const {
|
||||||
|
return x * x + y * y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only implemented for T=float
|
||||||
|
[[nodiscard]] float Length() const;
|
||||||
|
[[nodiscard]] float Normalize(); // returns the previous length, which is often useful
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr T& operator[](std::size_t i) {
|
||||||
|
return *((&x) + i);
|
||||||
|
}
|
||||||
|
[[nodiscard]] constexpr const T& operator[](std::size_t i) const {
|
||||||
|
return *((&x) + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr void SetZero() {
|
||||||
|
x = 0;
|
||||||
|
y = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Common aliases: UV (texel coordinates), ST (texture coordinates)
|
||||||
|
[[nodiscard]] constexpr T& u() {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
[[nodiscard]] constexpr T& v() {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
[[nodiscard]] constexpr T& s() {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
[[nodiscard]] constexpr T& t() {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr const T& u() const {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
[[nodiscard]] constexpr const T& v() const {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
[[nodiscard]] constexpr const T& s() const {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
[[nodiscard]] constexpr const T& t() const {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// swizzlers - create a subvector of specific components
|
||||||
|
[[nodiscard]] constexpr Vec2 yx() const {
|
||||||
|
return Vec2(y, x);
|
||||||
|
}
|
||||||
|
[[nodiscard]] constexpr Vec2 vu() const {
|
||||||
|
return Vec2(y, x);
|
||||||
|
}
|
||||||
|
[[nodiscard]] constexpr Vec2 ts() const {
|
||||||
|
return Vec2(y, x);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, size_t N, typename V>
|
template <typename T, typename V>
|
||||||
[[nodiscard]] constexpr Vec<T, N> operator*(const V f, const Vec<T, N> v) noexcept {
|
[[nodiscard]] constexpr Vec2<T> operator*(const V& f, const Vec2<T>& vec) {
|
||||||
using C = std::common_type_t<T, V>;
|
using C = std::common_type_t<T, V>;
|
||||||
Vec<T, N> r{};
|
|
||||||
for (size_t i = 0; i < N; ++i)
|
return Vec2<T>(static_cast<T>(static_cast<C>(f) * static_cast<C>(vec.x)),
|
||||||
r.elems[i] = T(C(f) * C(v.elems[i]));
|
static_cast<T>(static_cast<C>(f) * static_cast<C>(vec.y)));
|
||||||
return r;
|
}
|
||||||
|
|
||||||
|
using Vec2f = Vec2<float>;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline float Vec2<float>::Length() const {
|
||||||
|
return std::sqrt(x * x + y * y);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline float Vec2<float>::Normalize() {
|
||||||
|
float length = Length();
|
||||||
|
*this /= length;
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class Vec3 {
|
||||||
|
public:
|
||||||
|
T x{};
|
||||||
|
T y{};
|
||||||
|
T z{};
|
||||||
|
|
||||||
|
constexpr Vec3() = default;
|
||||||
|
constexpr Vec3(const T& x_, const T& y_, const T& z_) : x(x_), y(y_), z(z_) {}
|
||||||
|
|
||||||
|
template <typename T2>
|
||||||
|
[[nodiscard]] constexpr Vec3<T2> Cast() const {
|
||||||
|
return Vec3<T2>(static_cast<T2>(x), static_cast<T2>(y), static_cast<T2>(z));
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] static constexpr Vec3 AssignToAll(const T& f) {
|
||||||
|
return Vec3(f, f, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr Vec3<decltype(T{} + T{})> operator+(const Vec3& other) const {
|
||||||
|
return {x + other.x, y + other.y, z + other.z};
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr Vec3& operator+=(const Vec3& other) {
|
||||||
|
x += other.x;
|
||||||
|
y += other.y;
|
||||||
|
z += other.z;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr Vec3<decltype(T{} - T{})> operator-(const Vec3& other) const {
|
||||||
|
return {x - other.x, y - other.y, z - other.z};
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr Vec3& operator-=(const Vec3& other) {
|
||||||
|
x -= other.x;
|
||||||
|
y -= other.y;
|
||||||
|
z -= other.z;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename U = T>
|
||||||
|
[[nodiscard]] constexpr Vec3<std::enable_if_t<std::is_signed_v<U>, U>> operator-() const {
|
||||||
|
return {-x, -y, -z};
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr Vec3<decltype(T{} * T{})> operator*(const Vec3& other) const {
|
||||||
|
return {x * other.x, y * other.y, z * other.z};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename V>
|
||||||
|
[[nodiscard]] constexpr Vec3<decltype(T{} * V{})> operator*(const V& f) const {
|
||||||
|
using TV = decltype(T{} * V{});
|
||||||
|
using C = std::common_type_t<T, V>;
|
||||||
|
|
||||||
|
return {
|
||||||
|
static_cast<TV>(static_cast<C>(x) * static_cast<C>(f)),
|
||||||
|
static_cast<TV>(static_cast<C>(y) * static_cast<C>(f)),
|
||||||
|
static_cast<TV>(static_cast<C>(z) * static_cast<C>(f)),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename V>
|
||||||
|
constexpr Vec3& operator*=(const V& f) {
|
||||||
|
*this = *this * f;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
template <typename V>
|
||||||
|
[[nodiscard]] constexpr Vec3<decltype(T{} / V{})> operator/(const V& f) const {
|
||||||
|
using TV = decltype(T{} / V{});
|
||||||
|
using C = std::common_type_t<T, V>;
|
||||||
|
|
||||||
|
return {
|
||||||
|
static_cast<TV>(static_cast<C>(x) / static_cast<C>(f)),
|
||||||
|
static_cast<TV>(static_cast<C>(y) / static_cast<C>(f)),
|
||||||
|
static_cast<TV>(static_cast<C>(z) / static_cast<C>(f)),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename V>
|
||||||
|
constexpr Vec3& operator/=(const V& f) {
|
||||||
|
*this = *this / f;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RotateFromOrigin(float roll, float pitch, float yaw) {
|
||||||
|
float temp = y;
|
||||||
|
y = std::cos(roll) * y - std::sin(roll) * z;
|
||||||
|
z = std::sin(roll) * temp + std::cos(roll) * z;
|
||||||
|
|
||||||
|
temp = x;
|
||||||
|
x = std::cos(pitch) * x + std::sin(pitch) * z;
|
||||||
|
z = -std::sin(pitch) * temp + std::cos(pitch) * z;
|
||||||
|
|
||||||
|
temp = x;
|
||||||
|
x = std::cos(yaw) * x - std::sin(yaw) * y;
|
||||||
|
y = std::sin(yaw) * temp + std::cos(yaw) * y;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr T Length2() const {
|
||||||
|
return x * x + y * y + z * z;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only implemented for T=float
|
||||||
|
[[nodiscard]] float Length() const;
|
||||||
|
[[nodiscard]] Vec3 Normalized() const;
|
||||||
|
[[nodiscard]] float Normalize(); // returns the previous length, which is often useful
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr T& operator[](std::size_t i) {
|
||||||
|
return *((&x) + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr const T& operator[](std::size_t i) const {
|
||||||
|
return *((&x) + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr void SetZero() {
|
||||||
|
x = 0;
|
||||||
|
y = 0;
|
||||||
|
z = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Common aliases: UVW (texel coordinates), RGB (colors), STQ (texture coordinates)
|
||||||
|
[[nodiscard]] constexpr T& u() {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
[[nodiscard]] constexpr T& v() {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
[[nodiscard]] constexpr T& w() {
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr T& r() {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
[[nodiscard]] constexpr T& g() {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
[[nodiscard]] constexpr T& b() {
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr T& s() {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
[[nodiscard]] constexpr T& t() {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
[[nodiscard]] constexpr T& q() {
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr const T& u() const {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
[[nodiscard]] constexpr const T& v() const {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
[[nodiscard]] constexpr const T& w() const {
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr const T& r() const {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
[[nodiscard]] constexpr const T& g() const {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
[[nodiscard]] constexpr const T& b() const {
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr const T& s() const {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
[[nodiscard]] constexpr const T& t() const {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
[[nodiscard]] constexpr const T& q() const {
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
|
||||||
|
// swizzlers - create a subvector of specific components
|
||||||
|
// e.g. Vec2 uv() { return Vec2(x,y); }
|
||||||
|
// _DEFINE_SWIZZLER2 defines a single such function, DEFINE_SWIZZLER2 defines all of them for all
|
||||||
|
// component names (x<->r) and permutations (xy<->yx)
|
||||||
|
#define _DEFINE_SWIZZLER2(a, b, name) \
|
||||||
|
[[nodiscard]] constexpr Vec2<T> name() const { return Vec2<T>(a, b); }
|
||||||
|
#define DEFINE_SWIZZLER2(a, b, a2, b2, a3, b3, a4, b4) \
|
||||||
|
_DEFINE_SWIZZLER2(a, b, a##b); \
|
||||||
|
_DEFINE_SWIZZLER2(a, b, a2##b2); \
|
||||||
|
_DEFINE_SWIZZLER2(a, b, a3##b3); \
|
||||||
|
_DEFINE_SWIZZLER2(a, b, a4##b4); \
|
||||||
|
_DEFINE_SWIZZLER2(b, a, b##a); \
|
||||||
|
_DEFINE_SWIZZLER2(b, a, b2##a2); \
|
||||||
|
_DEFINE_SWIZZLER2(b, a, b3##a3); \
|
||||||
|
_DEFINE_SWIZZLER2(b, a, b4##a4)
|
||||||
|
|
||||||
|
DEFINE_SWIZZLER2(x, y, r, g, u, v, s, t);
|
||||||
|
DEFINE_SWIZZLER2(x, z, r, b, u, w, s, q);
|
||||||
|
DEFINE_SWIZZLER2(y, z, g, b, v, w, t, q);
|
||||||
|
#undef DEFINE_SWIZZLER2
|
||||||
|
#undef _DEFINE_SWIZZLER2
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename V>
|
||||||
|
[[nodiscard]] constexpr Vec3<T> operator*(const V& f, const Vec3<T>& vec) {
|
||||||
|
using C = std::common_type_t<T, V>;
|
||||||
|
|
||||||
|
return Vec3<T>(static_cast<T>(static_cast<C>(f) * static_cast<C>(vec.x)),
|
||||||
|
static_cast<T>(static_cast<C>(f) * static_cast<C>(vec.y)),
|
||||||
|
static_cast<T>(static_cast<C>(f) * static_cast<C>(vec.z)));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline float Vec3<float>::Length() const {
|
||||||
|
return std::sqrt(x * x + y * y + z * z);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline Vec3<float> Vec3<float>::Normalized() const {
|
||||||
|
return *this / Length();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline float Vec3<float>::Normalize() {
|
||||||
|
float length = Length();
|
||||||
|
*this /= length;
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
using Vec3f = Vec3<float>;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class Vec4 {
|
||||||
|
public:
|
||||||
|
T x{};
|
||||||
|
T y{};
|
||||||
|
T z{};
|
||||||
|
T w{};
|
||||||
|
|
||||||
|
constexpr Vec4() = default;
|
||||||
|
constexpr Vec4(const T& x_, const T& y_, const T& z_, const T& w_)
|
||||||
|
: x(x_), y(y_), z(z_), w(w_) {}
|
||||||
|
|
||||||
|
template <typename T2>
|
||||||
|
[[nodiscard]] constexpr Vec4<T2> Cast() const {
|
||||||
|
return Vec4<T2>(static_cast<T2>(x), static_cast<T2>(y), static_cast<T2>(z),
|
||||||
|
static_cast<T2>(w));
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] static constexpr Vec4 AssignToAll(const T& f) {
|
||||||
|
return Vec4(f, f, f, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr Vec4<decltype(T{} + T{})> operator+(const Vec4& other) const {
|
||||||
|
return {x + other.x, y + other.y, z + other.z, w + other.w};
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr Vec4& operator+=(const Vec4& other) {
|
||||||
|
x += other.x;
|
||||||
|
y += other.y;
|
||||||
|
z += other.z;
|
||||||
|
w += other.w;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr Vec4<decltype(T{} - T{})> operator-(const Vec4& other) const {
|
||||||
|
return {x - other.x, y - other.y, z - other.z, w - other.w};
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr Vec4& operator-=(const Vec4& other) {
|
||||||
|
x -= other.x;
|
||||||
|
y -= other.y;
|
||||||
|
z -= other.z;
|
||||||
|
w -= other.w;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename U = T>
|
||||||
|
[[nodiscard]] constexpr Vec4<std::enable_if_t<std::is_signed_v<U>, U>> operator-() const {
|
||||||
|
return {-x, -y, -z, -w};
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr Vec4<decltype(T{} * T{})> operator*(const Vec4& other) const {
|
||||||
|
return {x * other.x, y * other.y, z * other.z, w * other.w};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename V>
|
||||||
|
[[nodiscard]] constexpr Vec4<decltype(T{} * V{})> operator*(const V& f) const {
|
||||||
|
using TV = decltype(T{} * V{});
|
||||||
|
using C = std::common_type_t<T, V>;
|
||||||
|
|
||||||
|
return {
|
||||||
|
static_cast<TV>(static_cast<C>(x) * static_cast<C>(f)),
|
||||||
|
static_cast<TV>(static_cast<C>(y) * static_cast<C>(f)),
|
||||||
|
static_cast<TV>(static_cast<C>(z) * static_cast<C>(f)),
|
||||||
|
static_cast<TV>(static_cast<C>(w) * static_cast<C>(f)),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename V>
|
||||||
|
constexpr Vec4& operator*=(const V& f) {
|
||||||
|
*this = *this * f;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename V>
|
||||||
|
[[nodiscard]] constexpr Vec4<decltype(T{} / V{})> operator/(const V& f) const {
|
||||||
|
using TV = decltype(T{} / V{});
|
||||||
|
using C = std::common_type_t<T, V>;
|
||||||
|
|
||||||
|
return {
|
||||||
|
static_cast<TV>(static_cast<C>(x) / static_cast<C>(f)),
|
||||||
|
static_cast<TV>(static_cast<C>(y) / static_cast<C>(f)),
|
||||||
|
static_cast<TV>(static_cast<C>(z) / static_cast<C>(f)),
|
||||||
|
static_cast<TV>(static_cast<C>(w) / static_cast<C>(f)),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename V>
|
||||||
|
constexpr Vec4& operator/=(const V& f) {
|
||||||
|
*this = *this / f;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr T Length2() const {
|
||||||
|
return x * x + y * y + z * z + w * w;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr T& operator[](std::size_t i) {
|
||||||
|
return *((&x) + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr const T& operator[](std::size_t i) const {
|
||||||
|
return *((&x) + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr void SetZero() {
|
||||||
|
x = 0;
|
||||||
|
y = 0;
|
||||||
|
z = 0;
|
||||||
|
w = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Common alias: RGBA (colors)
|
||||||
|
[[nodiscard]] constexpr T& r() {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
[[nodiscard]] constexpr T& g() {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
[[nodiscard]] constexpr T& b() {
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
[[nodiscard]] constexpr T& a() {
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr const T& r() const {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
[[nodiscard]] constexpr const T& g() const {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
[[nodiscard]] constexpr const T& b() const {
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
[[nodiscard]] constexpr const T& a() const {
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Swizzlers - Create a subvector of specific components
|
||||||
|
// e.g. Vec2 uv() { return Vec2(x,y); }
|
||||||
|
|
||||||
|
// _DEFINE_SWIZZLER2 defines a single such function
|
||||||
|
// DEFINE_SWIZZLER2_COMP1 defines one-component functions for all component names (x<->r)
|
||||||
|
// DEFINE_SWIZZLER2_COMP2 defines two component functions for all component names (x<->r) and
|
||||||
|
// permutations (xy<->yx)
|
||||||
|
#define _DEFINE_SWIZZLER2(a, b, name) \
|
||||||
|
[[nodiscard]] constexpr Vec2<T> name() const { return Vec2<T>(a, b); }
|
||||||
|
#define DEFINE_SWIZZLER2_COMP1(a, a2) \
|
||||||
|
_DEFINE_SWIZZLER2(a, a, a##a); \
|
||||||
|
_DEFINE_SWIZZLER2(a, a, a2##a2)
|
||||||
|
#define DEFINE_SWIZZLER2_COMP2(a, b, a2, b2) \
|
||||||
|
_DEFINE_SWIZZLER2(a, b, a##b); \
|
||||||
|
_DEFINE_SWIZZLER2(a, b, a2##b2); \
|
||||||
|
_DEFINE_SWIZZLER2(b, a, b##a); \
|
||||||
|
_DEFINE_SWIZZLER2(b, a, b2##a2)
|
||||||
|
|
||||||
|
DEFINE_SWIZZLER2_COMP2(x, y, r, g);
|
||||||
|
DEFINE_SWIZZLER2_COMP2(x, z, r, b);
|
||||||
|
DEFINE_SWIZZLER2_COMP2(x, w, r, a);
|
||||||
|
DEFINE_SWIZZLER2_COMP2(y, z, g, b);
|
||||||
|
DEFINE_SWIZZLER2_COMP2(y, w, g, a);
|
||||||
|
DEFINE_SWIZZLER2_COMP2(z, w, b, a);
|
||||||
|
DEFINE_SWIZZLER2_COMP1(x, r);
|
||||||
|
DEFINE_SWIZZLER2_COMP1(y, g);
|
||||||
|
DEFINE_SWIZZLER2_COMP1(z, b);
|
||||||
|
DEFINE_SWIZZLER2_COMP1(w, a);
|
||||||
|
#undef DEFINE_SWIZZLER2_COMP1
|
||||||
|
#undef DEFINE_SWIZZLER2_COMP2
|
||||||
|
#undef _DEFINE_SWIZZLER2
|
||||||
|
|
||||||
|
#define _DEFINE_SWIZZLER3(a, b, c, name) \
|
||||||
|
[[nodiscard]] constexpr Vec3<T> name() const { return Vec3<T>(a, b, c); }
|
||||||
|
#define DEFINE_SWIZZLER3_COMP1(a, a2) \
|
||||||
|
_DEFINE_SWIZZLER3(a, a, a, a##a##a); \
|
||||||
|
_DEFINE_SWIZZLER3(a, a, a, a2##a2##a2)
|
||||||
|
#define DEFINE_SWIZZLER3_COMP3(a, b, c, a2, b2, c2) \
|
||||||
|
_DEFINE_SWIZZLER3(a, b, c, a##b##c); \
|
||||||
|
_DEFINE_SWIZZLER3(a, c, b, a##c##b); \
|
||||||
|
_DEFINE_SWIZZLER3(b, a, c, b##a##c); \
|
||||||
|
_DEFINE_SWIZZLER3(b, c, a, b##c##a); \
|
||||||
|
_DEFINE_SWIZZLER3(c, a, b, c##a##b); \
|
||||||
|
_DEFINE_SWIZZLER3(c, b, a, c##b##a); \
|
||||||
|
_DEFINE_SWIZZLER3(a, b, c, a2##b2##c2); \
|
||||||
|
_DEFINE_SWIZZLER3(a, c, b, a2##c2##b2); \
|
||||||
|
_DEFINE_SWIZZLER3(b, a, c, b2##a2##c2); \
|
||||||
|
_DEFINE_SWIZZLER3(b, c, a, b2##c2##a2); \
|
||||||
|
_DEFINE_SWIZZLER3(c, a, b, c2##a2##b2); \
|
||||||
|
_DEFINE_SWIZZLER3(c, b, a, c2##b2##a2)
|
||||||
|
|
||||||
|
DEFINE_SWIZZLER3_COMP3(x, y, z, r, g, b);
|
||||||
|
DEFINE_SWIZZLER3_COMP3(x, y, w, r, g, a);
|
||||||
|
DEFINE_SWIZZLER3_COMP3(x, z, w, r, b, a);
|
||||||
|
DEFINE_SWIZZLER3_COMP3(y, z, w, g, b, a);
|
||||||
|
DEFINE_SWIZZLER3_COMP1(x, r);
|
||||||
|
DEFINE_SWIZZLER3_COMP1(y, g);
|
||||||
|
DEFINE_SWIZZLER3_COMP1(z, b);
|
||||||
|
DEFINE_SWIZZLER3_COMP1(w, a);
|
||||||
|
#undef DEFINE_SWIZZLER3_COMP1
|
||||||
|
#undef DEFINE_SWIZZLER3_COMP3
|
||||||
|
#undef _DEFINE_SWIZZLER3
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename V>
|
||||||
|
[[nodiscard]] constexpr Vec4<decltype(V{} * T{})> operator*(const V& f, const Vec4<T>& vec) {
|
||||||
|
using TV = decltype(V{} * T{});
|
||||||
|
using C = std::common_type_t<T, V>;
|
||||||
|
|
||||||
|
return {
|
||||||
|
static_cast<TV>(static_cast<C>(f) * static_cast<C>(vec.x)),
|
||||||
|
static_cast<TV>(static_cast<C>(f) * static_cast<C>(vec.y)),
|
||||||
|
static_cast<TV>(static_cast<C>(f) * static_cast<C>(vec.z)),
|
||||||
|
static_cast<TV>(static_cast<C>(f) * static_cast<C>(vec.w)),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
using Vec4f = Vec4<float>;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
constexpr decltype(T{} * T{} + T{} * T{}) Dot(const Vec2<T>& a, const Vec2<T>& b) {
|
||||||
|
return a.x * b.x + a.y * b.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
[[nodiscard]] constexpr decltype(T{} * T{} + T{} * T{}) Dot(const Vec3<T>& a, const Vec3<T>& b) {
|
||||||
|
return a.x * b.x + a.y * b.y + a.z * b.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
[[nodiscard]] constexpr decltype(T{} * T{} + T{} * T{}) Dot(const Vec4<T>& a, const Vec4<T>& b) {
|
||||||
|
return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
[[nodiscard]] inline float Dot(const Vec4<float>& a, const Vec4<float>& b) {
|
||||||
|
#ifdef __ARM_NEON
|
||||||
|
float32x4_t va = vld1q_f32(&a.x);
|
||||||
|
float32x4_t vb = vld1q_f32(&b.x);
|
||||||
|
float32x4_t result = vmulq_f32(va, vb);
|
||||||
|
#if defined(__aarch64__) // Use vaddvq_f32 in ARMv8 architectures
|
||||||
|
return vaddvq_f32(result);
|
||||||
|
#else // Use manual addition for older architectures
|
||||||
|
float32x2_t sum2 = vadd_f32(vget_high_f32(result), vget_low_f32(result));
|
||||||
|
return vget_lane_f32(vpadd_f32(sum2, sum2), 0);
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
[[nodiscard]] constexpr Vec3<decltype(T{} * T{} - T{} * T{})> Cross(const Vec3<T>& a,
|
||||||
|
const Vec3<T>& b) {
|
||||||
|
return {a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x};
|
||||||
|
}
|
||||||
|
|
||||||
|
// linear interpolation via float: 0.0=begin, 1.0=end
|
||||||
|
template <typename X>
|
||||||
|
[[nodiscard]] constexpr decltype(X{} * float{} + X{} * float{}) Lerp(const X& begin, const X& end,
|
||||||
|
const float t) {
|
||||||
|
return begin * (1.f - t) + end * t;
|
||||||
|
}
|
||||||
|
|
||||||
|
// linear interpolation via int: 0=begin, base=end
|
||||||
|
template <typename X, int base>
|
||||||
|
[[nodiscard]] constexpr decltype((X{} * int{} + X{} * int{}) / base) LerpInt(const X& begin,
|
||||||
|
const X& end,
|
||||||
|
const int t) {
|
||||||
|
return (begin * (base - t) + end * t) / base;
|
||||||
|
}
|
||||||
|
|
||||||
|
// bilinear interpolation. s is for interpolating x00-x01 and x10-x11, and t is for the second
|
||||||
|
// interpolation.
|
||||||
|
template <typename X>
|
||||||
|
[[nodiscard]] constexpr auto BilinearInterp(const X& x00, const X& x01, const X& x10, const X& x11,
|
||||||
|
const float s, const float t) {
|
||||||
|
auto y0 = Lerp(x00, x01, s);
|
||||||
|
auto y1 = Lerp(x10, x11, s);
|
||||||
|
return Lerp(y0, y1, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Utility vector factories
|
||||||
|
template <typename T>
|
||||||
|
[[nodiscard]] constexpr Vec2<T> MakeVec(const T& x, const T& y) {
|
||||||
|
return Vec2<T>{x, y};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
[[nodiscard]] constexpr Vec3<T> MakeVec(const T& x, const T& y, const T& z) {
|
||||||
|
return Vec3<T>{x, y, z};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
[[nodiscard]] constexpr Vec4<T> MakeVec(const T& x, const T& y, const Vec2<T>& zw) {
|
||||||
|
return MakeVec(x, y, zw[0], zw[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
[[nodiscard]] constexpr Vec3<T> MakeVec(const Vec2<T>& xy, const T& z) {
|
||||||
|
return MakeVec(xy[0], xy[1], z);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
[[nodiscard]] constexpr Vec3<T> MakeVec(const T& x, const Vec2<T>& yz) {
|
||||||
|
return MakeVec(x, yz[0], yz[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
[[nodiscard]] constexpr Vec4<T> MakeVec(const T& x, const T& y, const T& z, const T& w) {
|
||||||
|
return Vec4<T>{x, y, z, w};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
[[nodiscard]] constexpr Vec4<T> MakeVec(const Vec2<T>& xy, const T& z, const T& w) {
|
||||||
|
return MakeVec(xy[0], xy[1], z, w);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
[[nodiscard]] constexpr Vec4<T> MakeVec(const T& x, const Vec2<T>& yz, const T& w) {
|
||||||
|
return MakeVec(x, yz[0], yz[1], w);
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: This has priority over "Vec2<Vec2<T>> MakeVec(const Vec2<T>& x, const Vec2<T>& y)".
|
||||||
|
// Even if someone wanted to use an odd object like Vec2<Vec2<T>>, the compiler would error
|
||||||
|
// out soon enough due to misuse of the returned structure.
|
||||||
|
template <typename T>
|
||||||
|
[[nodiscard]] constexpr Vec4<T> MakeVec(const Vec2<T>& xy, const Vec2<T>& zw) {
|
||||||
|
return MakeVec(xy[0], xy[1], zw[0], zw[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
[[nodiscard]] constexpr Vec4<T> MakeVec(const Vec3<T>& xyz, const T& w) {
|
||||||
|
return MakeVec(xyz[0], xyz[1], xyz[2], w);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
[[nodiscard]] constexpr Vec4<T> MakeVec(const T& x, const Vec3<T>& yzw) {
|
||||||
|
return MakeVec(x, yzw[0], yzw[1], yzw[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Common
|
} // namespace Common
|
||||||
|
|||||||
@@ -121,10 +121,7 @@ union Exclusive {
|
|||||||
constexpr explicit Exclusive(u32 raw_) : raw{raw_} {}
|
constexpr explicit Exclusive(u32 raw_) : raw{raw_} {}
|
||||||
|
|
||||||
constexpr bool Verify() {
|
constexpr bool Verify() {
|
||||||
if (this->GetSig() != 0x10) return false;
|
return this->GetSig() == 0x10;
|
||||||
const bool pair = decltype(l)::ExtractValue(raw) & 1;
|
|
||||||
const bool fixed_rt2 = decltype(rt2)::ExtractValue(raw) == 0b11111;
|
|
||||||
return pair || fixed_rt2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr u32 GetSig() {
|
constexpr u32 GetSig() {
|
||||||
|
|||||||
@@ -10,15 +10,17 @@
|
|||||||
#include "core/hle/kernel/k_process.h"
|
#include "core/hle/kernel/k_process.h"
|
||||||
#include "core/hle/kernel/k_resource_limit.h"
|
#include "core/hle/kernel/k_resource_limit.h"
|
||||||
#include "core/hle/kernel/svc.h"
|
#include "core/hle/kernel/svc.h"
|
||||||
#include "core/hle/kernel/svc_results.h"
|
|
||||||
#include "core/hle/kernel/svc_version.h"
|
|
||||||
|
|
||||||
namespace Kernel::Svc {
|
namespace Kernel::Svc {
|
||||||
|
|
||||||
/// Gets system/memory information for the current process
|
/// Gets system/memory information for the current process
|
||||||
Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle handle, u64 info_sub_id) {
|
Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle handle,
|
||||||
LOG_TRACE(Kernel_SVC, "called info_id={:#x}, info_sub_id={:#x}, handle={:#08x}", info_id_type, info_sub_id, handle);
|
u64 info_sub_id) {
|
||||||
u32 info_id = u32(info_id_type);
|
LOG_TRACE(Kernel_SVC, "called info_id={:#x}, info_sub_id={:#x}, handle={:#08x}",
|
||||||
|
info_id_type, info_sub_id, handle);
|
||||||
|
|
||||||
|
u32 info_id = static_cast<u32>(info_id_type);
|
||||||
|
|
||||||
switch (info_id_type) {
|
switch (info_id_type) {
|
||||||
case InfoType::CoreMask:
|
case InfoType::CoreMask:
|
||||||
case InfoType::PriorityMask:
|
case InfoType::PriorityMask:
|
||||||
@@ -51,123 +53,152 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle
|
|||||||
case InfoType::CoreMask:
|
case InfoType::CoreMask:
|
||||||
*result = process->GetCoreMask();
|
*result = process->GetCoreMask();
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
|
|
||||||
case InfoType::PriorityMask:
|
case InfoType::PriorityMask:
|
||||||
*result = process->GetPriorityMask();
|
*result = process->GetPriorityMask();
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
|
|
||||||
case InfoType::AliasRegionAddress:
|
case InfoType::AliasRegionAddress:
|
||||||
*result = GetInteger(process->GetPageTable().GetAliasRegionStart());
|
*result = GetInteger(process->GetPageTable().GetAliasRegionStart());
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
|
|
||||||
case InfoType::AliasRegionSize:
|
case InfoType::AliasRegionSize:
|
||||||
*result = process->GetPageTable().GetAliasRegionSize();
|
*result = process->GetPageTable().GetAliasRegionSize();
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
case InfoType::HeapRegionAddress:
|
case InfoType::HeapRegionAddress:
|
||||||
*result = GetInteger(process->GetPageTable().GetHeapRegionStart());
|
*result = GetInteger(process->GetPageTable().GetHeapRegionStart());
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
|
|
||||||
case InfoType::HeapRegionSize:
|
case InfoType::HeapRegionSize:
|
||||||
*result = process->GetPageTable().GetHeapRegionSize();
|
*result = process->GetPageTable().GetHeapRegionSize();
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
|
|
||||||
case InfoType::AslrRegionAddress:
|
case InfoType::AslrRegionAddress:
|
||||||
*result = GetInteger(process->GetPageTable().GetAliasCodeRegionStart());
|
*result = GetInteger(process->GetPageTable().GetAliasCodeRegionStart());
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
|
|
||||||
case InfoType::AslrRegionSize:
|
case InfoType::AslrRegionSize:
|
||||||
*result = process->GetPageTable().GetAliasCodeRegionSize();
|
*result = process->GetPageTable().GetAliasCodeRegionSize();
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
|
|
||||||
case InfoType::StackRegionAddress:
|
case InfoType::StackRegionAddress:
|
||||||
*result = GetInteger(process->GetPageTable().GetStackRegionStart());
|
*result = GetInteger(process->GetPageTable().GetStackRegionStart());
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
|
|
||||||
case InfoType::StackRegionSize:
|
case InfoType::StackRegionSize:
|
||||||
*result = process->GetPageTable().GetStackRegionSize();
|
*result = process->GetPageTable().GetStackRegionSize();
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
|
|
||||||
case InfoType::TotalMemorySize:
|
case InfoType::TotalMemorySize:
|
||||||
*result = process->GetTotalUserPhysicalMemorySize(system.Kernel());
|
*result = process->GetTotalUserPhysicalMemorySize(system.Kernel());
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
|
|
||||||
case InfoType::UsedMemorySize:
|
case InfoType::UsedMemorySize:
|
||||||
*result = process->GetUsedUserPhysicalMemorySize(system.Kernel());
|
*result = process->GetUsedUserPhysicalMemorySize(system.Kernel());
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
|
|
||||||
case InfoType::SystemResourceSizeTotal:
|
case InfoType::SystemResourceSizeTotal:
|
||||||
*result = process->GetTotalSystemResourceSize();
|
*result = process->GetTotalSystemResourceSize();
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
|
|
||||||
case InfoType::SystemResourceSizeUsed:
|
case InfoType::SystemResourceSizeUsed:
|
||||||
*result = process->GetUsedSystemResourceSize();
|
*result = process->GetUsedSystemResourceSize();
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
|
|
||||||
case InfoType::ProgramId:
|
case InfoType::ProgramId:
|
||||||
*result = process->GetProgramId();
|
*result = process->GetProgramId();
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
|
|
||||||
case InfoType::UserExceptionContextAddress:
|
case InfoType::UserExceptionContextAddress:
|
||||||
*result = GetInteger(process->GetProcessLocalRegionAddress());
|
*result = GetInteger(process->GetProcessLocalRegionAddress());
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
|
|
||||||
case InfoType::TotalNonSystemMemorySize:
|
case InfoType::TotalNonSystemMemorySize:
|
||||||
*result = process->GetTotalNonSystemUserPhysicalMemorySize(system.Kernel());
|
*result = process->GetTotalNonSystemUserPhysicalMemorySize(system.Kernel());
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
|
|
||||||
case InfoType::UsedNonSystemMemorySize:
|
case InfoType::UsedNonSystemMemorySize:
|
||||||
*result = process->GetUsedNonSystemUserPhysicalMemorySize(system.Kernel());
|
*result = process->GetUsedNonSystemUserPhysicalMemorySize(system.Kernel());
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
|
|
||||||
case InfoType::IsApplication:
|
case InfoType::IsApplication:
|
||||||
*result = process->IsApplication();
|
*result = process->IsApplication();
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
|
|
||||||
case InfoType::FreeThreadCount:
|
case InfoType::FreeThreadCount:
|
||||||
if (KResourceLimit* resource_limit = process->GetResourceLimit();
|
if (KResourceLimit* resource_limit = process->GetResourceLimit();
|
||||||
resource_limit != nullptr) {
|
resource_limit != nullptr) {
|
||||||
const auto current_value = resource_limit->GetCurrentValue(Svc::LimitableResource::ThreadCountMax);
|
const auto current_value =
|
||||||
const auto limit_value = resource_limit->GetLimitValue(Svc::LimitableResource::ThreadCountMax);
|
resource_limit->GetCurrentValue(Svc::LimitableResource::ThreadCountMax);
|
||||||
|
const auto limit_value =
|
||||||
|
resource_limit->GetLimitValue(Svc::LimitableResource::ThreadCountMax);
|
||||||
*result = limit_value - current_value;
|
*result = limit_value - current_value;
|
||||||
} else {
|
} else {
|
||||||
*result = 0;
|
*result = 0;
|
||||||
}
|
}
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
|
|
||||||
case InfoType::AliasRegionExtraSize: {
|
case InfoType::AliasRegionExtraSize: {
|
||||||
R_UNLESS(info_sub_id == 0, ResultInvalidCombination);
|
if (info_sub_id != 0) {
|
||||||
|
return ResultInvalidCombination;
|
||||||
|
}
|
||||||
|
|
||||||
KProcess* current_process = GetCurrentProcessPointer(system.Kernel());
|
KProcess* current_process = GetCurrentProcessPointer(system.Kernel());
|
||||||
*result = current_process->GetPageTable().GetAliasRegionExtraSize();
|
*result = current_process->GetPageTable().GetAliasRegionExtraSize();
|
||||||
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_ERROR(Kernel_SVC, "Unimplemented svcGetInfo id={:#016x}", info_id);
|
LOG_ERROR(Kernel_SVC, "Unimplemented svcGetInfo id={:#016x}", info_id);
|
||||||
R_THROW(ResultInvalidEnumValue);
|
R_THROW(ResultInvalidEnumValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
case InfoType::DebuggerAttached:
|
case InfoType::DebuggerAttached:
|
||||||
*result = 0;
|
*result = 0;
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
|
|
||||||
case InfoType::ResourceLimit: {
|
case InfoType::ResourceLimit: {
|
||||||
R_UNLESS(handle == 0, ResultInvalidHandle);
|
R_UNLESS(handle == 0, ResultInvalidHandle);
|
||||||
R_UNLESS(info_sub_id == 0, ResultInvalidCombination);
|
R_UNLESS(info_sub_id == 0, ResultInvalidCombination);
|
||||||
|
|
||||||
KProcess* const current_process = GetCurrentProcessPointer(system.Kernel());
|
KProcess* const current_process = GetCurrentProcessPointer(system.Kernel());
|
||||||
KHandleTable& handle_table = current_process->GetHandleTable();
|
KHandleTable& handle_table = current_process->GetHandleTable();
|
||||||
if (auto const resource_limit = current_process->GetResourceLimit(); resource_limit) {
|
const auto resource_limit = current_process->GetResourceLimit();
|
||||||
Handle resource_handle{};
|
if (!resource_limit) {
|
||||||
R_TRY(handle_table.Add(system.Kernel(), std::addressof(resource_handle), resource_limit));
|
|
||||||
*result = resource_handle;
|
|
||||||
} else {
|
|
||||||
*result = Svc::InvalidHandle;
|
*result = Svc::InvalidHandle;
|
||||||
|
// Yes, the kernel considers this a successful operation.
|
||||||
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
// Yes, the kernel considers this a successful operation either way.
|
|
||||||
|
Handle resource_handle{};
|
||||||
|
R_TRY(handle_table.Add(system.Kernel(), std::addressof(resource_handle), resource_limit));
|
||||||
|
|
||||||
|
*result = resource_handle;
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
case InfoType::RandomEntropy:
|
case InfoType::RandomEntropy:
|
||||||
R_UNLESS(handle == 0, ResultInvalidHandle);
|
R_UNLESS(handle == 0, ResultInvalidHandle);
|
||||||
R_UNLESS(info_sub_id < 4, ResultInvalidCombination);
|
R_UNLESS(info_sub_id < 4, ResultInvalidCombination);
|
||||||
|
|
||||||
*result = GetCurrentProcess(system.Kernel()).GetRandomEntropy(info_sub_id);
|
*result = GetCurrentProcess(system.Kernel()).GetRandomEntropy(info_sub_id);
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
case InfoType::InitialProcessIdRange: {
|
|
||||||
LOG_WARNING(Kernel_SVC, "(STUBBED) Attempted to query privileged process id bounds, returned 0/64");
|
case InfoType::InitialProcessIdRange:
|
||||||
R_UNLESS(handle == InvalidHandle, ResultInvalidHandle);
|
LOG_WARNING(Kernel_SVC,
|
||||||
switch (InitialProcessIdRangeInfo(info_sub_id)) {
|
"(STUBBED) Attempted to query privileged process id bounds, returned 0");
|
||||||
case InitialProcessIdRangeInfo::Minimum:
|
*result = 0;
|
||||||
*result = 0; //todo
|
R_SUCCEED();
|
||||||
R_SUCCEED();
|
|
||||||
case InitialProcessIdRangeInfo::Maximum:
|
|
||||||
*result = 64; //todo
|
|
||||||
R_SUCCEED();
|
|
||||||
default:
|
|
||||||
R_THROW(ResultInvalidCombination);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case InfoType::ThreadTickCount: {
|
case InfoType::ThreadTickCount: {
|
||||||
constexpr u64 num_cpus = 4;
|
constexpr u64 num_cpus = 4;
|
||||||
if (info_sub_id != 0xFFFFFFFFFFFFFFFF && info_sub_id >= num_cpus) {
|
if (info_sub_id != 0xFFFFFFFFFFFFFFFF && info_sub_id >= num_cpus) {
|
||||||
LOG_ERROR(Kernel_SVC, "Core count is out of range, expected {} but got {}", num_cpus, info_sub_id);
|
LOG_ERROR(Kernel_SVC, "Core count is out of range, expected {} but got {}", num_cpus,
|
||||||
|
info_sub_id);
|
||||||
R_THROW(ResultInvalidCombination);
|
R_THROW(ResultInvalidCombination);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,7 +206,8 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle
|
|||||||
.GetHandleTable()
|
.GetHandleTable()
|
||||||
.GetObject<KThread>(system.Kernel(), Handle(handle));
|
.GetObject<KThread>(system.Kernel(), Handle(handle));
|
||||||
if (thread.IsNull()) {
|
if (thread.IsNull()) {
|
||||||
LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle={:#08x}", Handle(handle));
|
LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle={:#08x}",
|
||||||
|
static_cast<Handle>(handle));
|
||||||
R_THROW(ResultInvalidHandle);
|
R_THROW(ResultInvalidHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,6 +220,7 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle
|
|||||||
u64 out_ticks = 0;
|
u64 out_ticks = 0;
|
||||||
if (same_thread && info_sub_id == 0xFFFFFFFFFFFFFFFF) {
|
if (same_thread && info_sub_id == 0xFFFFFFFFFFFFFFFF) {
|
||||||
const u64 thread_ticks = current_thread->GetCpuTime();
|
const u64 thread_ticks = current_thread->GetCpuTime();
|
||||||
|
|
||||||
out_ticks = thread_ticks + (core_timing.GetClockTicks() - prev_ctx_ticks);
|
out_ticks = thread_ticks + (core_timing.GetClockTicks() - prev_ctx_ticks);
|
||||||
} else if (same_thread && info_sub_id == system.Kernel().CurrentPhysicalCoreIndex()) {
|
} else if (same_thread && info_sub_id == system.Kernel().CurrentPhysicalCoreIndex()) {
|
||||||
out_ticks = core_timing.GetClockTicks() - prev_ctx_ticks;
|
out_ticks = core_timing.GetClockTicks() - prev_ctx_ticks;
|
||||||
@@ -197,40 +230,19 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle
|
|||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
case InfoType::IdleTickCount: {
|
case InfoType::IdleTickCount: {
|
||||||
// Verify the requested core is valid.
|
|
||||||
const bool core_valid =
|
|
||||||
(info_sub_id == 0xFFFFFFFFFFFFFFFF)
|
|
||||||
|| (info_sub_id == u64(system.Kernel().CurrentPhysicalCoreIndex()));
|
|
||||||
R_UNLESS(core_valid, ResultInvalidCombination);
|
|
||||||
|
|
||||||
// Verify the input handle is invalid.
|
// Verify the input handle is invalid.
|
||||||
R_UNLESS(handle == InvalidHandle, ResultInvalidHandle);
|
R_UNLESS(handle == InvalidHandle, ResultInvalidHandle);
|
||||||
|
|
||||||
|
// Verify the requested core is valid.
|
||||||
|
const bool core_valid =
|
||||||
|
(info_sub_id == 0xFFFFFFFFFFFFFFFF) ||
|
||||||
|
(info_sub_id == static_cast<u64>(system.Kernel().CurrentPhysicalCoreIndex()));
|
||||||
|
R_UNLESS(core_valid, ResultInvalidCombination);
|
||||||
|
|
||||||
// Get the idle tick count.
|
// Get the idle tick count.
|
||||||
*result = system.Kernel().CurrentScheduler()->GetIdleThread()->GetCpuTime();
|
*result = system.Kernel().CurrentScheduler()->GetIdleThread()->GetCpuTime();
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
case InfoType::MesosphereMeta: {
|
|
||||||
enum MesosphereMetaInfo : u64 {
|
|
||||||
KernelVersion = 0,
|
|
||||||
IsKTraceEnabled = 1,
|
|
||||||
IsSingleStepEnabled = 2,
|
|
||||||
};
|
|
||||||
R_UNLESS(handle == InvalidHandle, ResultInvalidHandle);
|
|
||||||
switch (MesosphereMetaInfo(info_sub_id)) {
|
|
||||||
case MesosphereMetaInfo::KernelVersion:
|
|
||||||
*result = Kernel::Svc::SupportedKernelVersion;
|
|
||||||
R_SUCCEED();
|
|
||||||
case MesosphereMetaInfo::IsKTraceEnabled:
|
|
||||||
*result = 0;
|
|
||||||
R_SUCCEED();
|
|
||||||
case MesosphereMetaInfo::IsSingleStepEnabled:
|
|
||||||
*result = 0;
|
|
||||||
R_SUCCEED();
|
|
||||||
default:
|
|
||||||
R_THROW(ResultInvalidCombination);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case InfoType::MesosphereCurrentProcess: {
|
case InfoType::MesosphereCurrentProcess: {
|
||||||
// Verify the input handle is invalid.
|
// Verify the input handle is invalid.
|
||||||
R_UNLESS(handle == InvalidHandle, ResultInvalidHandle);
|
R_UNLESS(handle == InvalidHandle, ResultInvalidHandle);
|
||||||
@@ -243,11 +255,13 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle
|
|||||||
KHandleTable& handle_table = current_process->GetHandleTable();
|
KHandleTable& handle_table = current_process->GetHandleTable();
|
||||||
|
|
||||||
// Get a new handle for the current process.
|
// Get a new handle for the current process.
|
||||||
Handle tmp{};
|
Handle tmp;
|
||||||
R_TRY(handle_table.Add(system.Kernel(), std::addressof(tmp), current_process));
|
R_TRY(handle_table.Add(system.Kernel(), std::addressof(tmp), current_process));
|
||||||
|
|
||||||
// Set the output.
|
// Set the output.
|
||||||
*result = tmp;
|
*result = tmp;
|
||||||
|
|
||||||
|
// We succeeded.
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -1387,8 +1387,7 @@ public:
|
|||||||
{5, &ACC_U1::GetProfile, "GetProfile"},
|
{5, &ACC_U1::GetProfile, "GetProfile"},
|
||||||
{6, nullptr, "GetProfileDigest"},
|
{6, nullptr, "GetProfileDigest"},
|
||||||
{50, &ACC_U1::IsUserRegistrationRequestPermitted, "IsUserRegistrationRequestPermitted"},
|
{50, &ACC_U1::IsUserRegistrationRequestPermitted, "IsUserRegistrationRequestPermitted"},
|
||||||
{51, &ACC_U1::TrySelectUserWithoutInteractionDeprecated, "TrySelectUserWithoutInteractionDeprecated"},
|
{51, &ACC_U1::TrySelectUserWithoutInteraction, "TrySelectUserWithoutInteraction"},
|
||||||
{52, &ACC_U1::TrySelectUserWithoutInteraction, "TrySelectUserWithoutInteraction"},
|
|
||||||
{60, &ACC_U1::ListOpenContextStoredUsers, "ListOpenContextStoredUsers"},
|
{60, &ACC_U1::ListOpenContextStoredUsers, "ListOpenContextStoredUsers"},
|
||||||
{99, nullptr, "DebugActivateOpenContextRetention"},
|
{99, nullptr, "DebugActivateOpenContextRetention"},
|
||||||
{100, nullptr, "GetUserRegistrationNotifier"},
|
{100, nullptr, "GetUserRegistrationNotifier"},
|
||||||
|
|||||||
@@ -154,7 +154,6 @@ enum class AppletMessage : u32 {
|
|||||||
DetectLongPressingCaptureButton = 91,
|
DetectLongPressingCaptureButton = 91,
|
||||||
AlbumScreenShotTaken = 92,
|
AlbumScreenShotTaken = 92,
|
||||||
AlbumRecordingSaved = 93,
|
AlbumRecordingSaved = 93,
|
||||||
StartupLogoDisappeared = 95,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class LibraryAppletMode : u32 {
|
enum class LibraryAppletMode : u32 {
|
||||||
|
|||||||
@@ -91,7 +91,6 @@ struct Applet {
|
|||||||
// Common state
|
// Common state
|
||||||
bool sleep_lock_enabled{};
|
bool sleep_lock_enabled{};
|
||||||
bool vr_mode_enabled{};
|
bool vr_mode_enabled{};
|
||||||
bool vr_mode_enabled_3d{};
|
|
||||||
bool lcd_backlight_off_enabled{};
|
bool lcd_backlight_off_enabled{};
|
||||||
APM::CpuBoostMode boost_mode{};
|
APM::CpuBoostMode boost_mode{};
|
||||||
bool request_exit_to_library_applet_at_execute_next_program_enabled{};
|
bool request_exit_to_library_applet_at_execute_next_program_enabled{};
|
||||||
|
|||||||
@@ -73,16 +73,20 @@ Result DisplayLayerManager::CreateManagedDisplayLayer(u64* out_layer_id) {
|
|||||||
R_TRY(m_manager_display_service->CreateManagedLayer(
|
R_TRY(m_manager_display_service->CreateManagedLayer(
|
||||||
out_layer_id, 0, display_id, Service::AppletResourceUserId{m_process->GetProcessId()}));
|
out_layer_id, 0, display_id, Service::AppletResourceUserId{m_process->GetProcessId()}));
|
||||||
|
|
||||||
|
m_manager_display_service->SetLayerVisibility(m_visible, *out_layer_id);
|
||||||
|
(void)m_display_service->GetContainer()->SetLayerStackMask(*out_layer_id,
|
||||||
|
this->GetLayerStackMask());
|
||||||
|
|
||||||
if (m_applet_id != AppletId::Application) {
|
if (m_applet_id != AppletId::Application) {
|
||||||
(void)m_manager_display_service->SetLayerBlending(m_blending_enabled, *out_layer_id);
|
(void)m_manager_display_service->SetLayerBlending(m_blending_enabled, *out_layer_id);
|
||||||
if (m_applet_id == AppletId::OverlayDisplay) {
|
if (m_applet_id == AppletId::OverlayDisplay) {
|
||||||
(void)m_manager_display_service->SetLayerZIndex(-1, *out_layer_id);
|
(void)m_manager_display_service->SetLayerZIndex(Overlay, *out_layer_id);
|
||||||
(void)m_display_service->GetContainer()->SetLayerIsOverlay(*out_layer_id, true);
|
(void)m_display_service->GetContainer()->SetLayerIsOverlay(*out_layer_id, true);
|
||||||
} else {
|
} else {
|
||||||
(void)m_manager_display_service->SetLayerZIndex(1, *out_layer_id);
|
(void)m_manager_display_service->SetLayerZIndex(Foreground, *out_layer_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(void)m_display_service->GetContainer()->SetLayerZIndex(*out_layer_id, true);
|
|
||||||
m_managed_display_layers.emplace(*out_layer_id);
|
m_managed_display_layers.emplace(*out_layer_id);
|
||||||
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
@@ -122,11 +126,12 @@ Result DisplayLayerManager::IsSystemBufferSharingEnabled() {
|
|||||||
|
|
||||||
// Ensure the overlay layer is visible
|
// Ensure the overlay layer is visible
|
||||||
m_manager_display_service->SetLayerVisibility(m_visible, m_system_shared_layer_id);
|
m_manager_display_service->SetLayerVisibility(m_visible, m_system_shared_layer_id);
|
||||||
|
(void)m_display_service->GetContainer()->SetLayerStackMask(m_system_shared_layer_id,
|
||||||
|
this->GetLayerStackMask());
|
||||||
m_manager_display_service->SetLayerBlending(m_blending_enabled, m_system_shared_layer_id);
|
m_manager_display_service->SetLayerBlending(m_blending_enabled, m_system_shared_layer_id);
|
||||||
s32 initial_z = 1;
|
s32 initial_z = Foreground;
|
||||||
(void)m_display_service->GetContainer()->SetLayerZIndex(m_system_shared_layer_id, true);
|
|
||||||
if (m_applet_id == AppletId::OverlayDisplay) {
|
if (m_applet_id == AppletId::OverlayDisplay) {
|
||||||
initial_z = -1;
|
initial_z = Overlay;
|
||||||
(void)m_display_service->GetContainer()->SetLayerIsOverlay(m_system_shared_layer_id, true);
|
(void)m_display_service->GetContainer()->SetLayerIsOverlay(m_system_shared_layer_id, true);
|
||||||
}
|
}
|
||||||
m_manager_display_service->SetLayerZIndex(initial_z, m_system_shared_layer_id);
|
m_manager_display_service->SetLayerZIndex(initial_z, m_system_shared_layer_id);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||||
@@ -73,7 +73,8 @@ Result IAllSystemAppletProxiesService::OpenLibraryAppletProxy(
|
|||||||
|
|
||||||
Result IAllSystemAppletProxiesService::OpenOverlayAppletProxy(
|
Result IAllSystemAppletProxiesService::OpenOverlayAppletProxy(
|
||||||
Out<SharedPointer<IOverlayAppletProxy>> out_overlay_applet_proxy, ClientProcessId pid,
|
Out<SharedPointer<IOverlayAppletProxy>> out_overlay_applet_proxy, ClientProcessId pid,
|
||||||
InCopyHandle<Kernel::KProcess> process_handle) {
|
InCopyHandle<Kernel::KProcess> process_handle,
|
||||||
|
InLargeData<AppletAttribute, BufferAttr_HipcMapAlias> attribute) {
|
||||||
LOG_WARNING(Service_AM, "called");
|
LOG_WARNING(Service_AM, "called");
|
||||||
|
|
||||||
if (const auto applet = this->GetAppletFromProcessId(pid); applet) {
|
if (const auto applet = this->GetAppletFromProcessId(pid); applet) {
|
||||||
@@ -88,7 +89,8 @@ Result IAllSystemAppletProxiesService::OpenOverlayAppletProxy(
|
|||||||
|
|
||||||
Result IAllSystemAppletProxiesService::OpenSystemApplicationProxy(
|
Result IAllSystemAppletProxiesService::OpenSystemApplicationProxy(
|
||||||
Out<SharedPointer<IApplicationProxy>> out_system_application_proxy, ClientProcessId pid,
|
Out<SharedPointer<IApplicationProxy>> out_system_application_proxy, ClientProcessId pid,
|
||||||
InCopyHandle<Kernel::KProcess> process_handle) {
|
InCopyHandle<Kernel::KProcess> process_handle,
|
||||||
|
InLargeData<AppletAttribute, BufferAttr_HipcMapAlias> attribute) {
|
||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
if (const auto applet = this->GetAppletFromProcessId(pid); applet) {
|
if (const auto applet = this->GetAppletFromProcessId(pid); applet) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||||
@@ -36,13 +36,15 @@ private:
|
|||||||
InCopyHandle<Kernel::KProcess> process_handle,
|
InCopyHandle<Kernel::KProcess> process_handle,
|
||||||
InLargeData<AppletAttribute, BufferAttr_HipcMapAlias> attribute);
|
InLargeData<AppletAttribute, BufferAttr_HipcMapAlias> attribute);
|
||||||
Result OpenOverlayAppletProxy(Out<SharedPointer<IOverlayAppletProxy>> out_overlay_applet_proxy,
|
Result OpenOverlayAppletProxy(Out<SharedPointer<IOverlayAppletProxy>> out_overlay_applet_proxy,
|
||||||
ClientProcessId pid, InCopyHandle<Kernel::KProcess> process_handle);
|
ClientProcessId pid, InCopyHandle<Kernel::KProcess> process_handle,
|
||||||
|
InLargeData<AppletAttribute, BufferAttr_HipcMapAlias> attribute);
|
||||||
Result OpenLibraryAppletProxyOld(
|
Result OpenLibraryAppletProxyOld(
|
||||||
Out<SharedPointer<ILibraryAppletProxy>> out_library_applet_proxy, ClientProcessId pid,
|
Out<SharedPointer<ILibraryAppletProxy>> out_library_applet_proxy, ClientProcessId pid,
|
||||||
InCopyHandle<Kernel::KProcess> process_handle);
|
InCopyHandle<Kernel::KProcess> process_handle);
|
||||||
Result OpenSystemApplicationProxy(
|
Result OpenSystemApplicationProxy(
|
||||||
Out<SharedPointer<IApplicationProxy>> out_system_application_proxy, ClientProcessId pid,
|
Out<SharedPointer<IApplicationProxy>> out_system_application_proxy, ClientProcessId pid,
|
||||||
InCopyHandle<Kernel::KProcess> process_handle);
|
InCopyHandle<Kernel::KProcess> process_handle,
|
||||||
|
InLargeData<AppletAttribute, BufferAttr_HipcMapAlias> attribute);
|
||||||
Result GetSystemProcessCommonFunctions();
|
Result GetSystemProcessCommonFunctions();
|
||||||
Result GetAppletAlternativeFunctions();
|
Result GetAppletAlternativeFunctions();
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_, std::shared_ptr<Ap
|
|||||||
{14, nullptr, "GetWakeupCount"}, //11.0.0+
|
{14, nullptr, "GetWakeupCount"}, //11.0.0+
|
||||||
{15, nullptr, "Unknown15"}, //19.0.0+
|
{15, nullptr, "Unknown15"}, //19.0.0+
|
||||||
{20, D<&ICommonStateGetter::PushToGeneralChannel>, "PushToGeneralChannel"},
|
{20, D<&ICommonStateGetter::PushToGeneralChannel>, "PushToGeneralChannel"},
|
||||||
{30, D<&ICommonStateGetter::GetHomeButtonReaderLockAccessor>, "GetHomeButtonReaderLockAccessor"},
|
{30, nullptr, "GetHomeButtonReaderLockAccessor"},
|
||||||
{31, D<&ICommonStateGetter::GetReaderLockAccessorEx>, "GetReaderLockAccessorEx"}, //2.0.0+
|
{31, D<&ICommonStateGetter::GetReaderLockAccessorEx>, "GetReaderLockAccessorEx"}, //2.0.0+
|
||||||
{32, D<&ICommonStateGetter::GetWriterLockAccessorEx>, "GetWriterLockAccessorEx"}, //7.0.0+
|
{32, D<&ICommonStateGetter::GetWriterLockAccessorEx>, "GetWriterLockAccessorEx"}, //7.0.0+
|
||||||
{40, nullptr, "GetCradleFwVersion"}, //2.0.0+
|
{40, nullptr, "GetCradleFwVersion"}, //2.0.0+
|
||||||
@@ -65,7 +65,7 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_, std::shared_ptr<Ap
|
|||||||
{100, D<&ICommonStateGetter::SetHandlingHomeButtonShortPressedEnabled>, "SetHandlingHomeButtonShortPressedEnabled"},
|
{100, D<&ICommonStateGetter::SetHandlingHomeButtonShortPressedEnabled>, "SetHandlingHomeButtonShortPressedEnabled"},
|
||||||
{110, nullptr, "OpenMyGpuErrorHandler"},
|
{110, nullptr, "OpenMyGpuErrorHandler"},
|
||||||
{120, D<&ICommonStateGetter::GetAppletLaunchedHistory>, "GetAppletLaunchedHistory"}, //13.0.0+
|
{120, D<&ICommonStateGetter::GetAppletLaunchedHistory>, "GetAppletLaunchedHistory"}, //13.0.0+
|
||||||
{130, D<&ICommonStateGetter::EnableStartupLogoDisappearedMessage>, "EnableStartupLogoDisappearedMessage"}, //21.0.0+
|
{130, nullptr, "Unknown130"}, //21.0.0+
|
||||||
{200, D<&ICommonStateGetter::GetOperationModeSystemInfo>, "GetOperationModeSystemInfo"},
|
{200, D<&ICommonStateGetter::GetOperationModeSystemInfo>, "GetOperationModeSystemInfo"},
|
||||||
{300, D<&ICommonStateGetter::GetSettingsPlatformRegion>, "GetSettingsPlatformRegion"},
|
{300, D<&ICommonStateGetter::GetSettingsPlatformRegion>, "GetSettingsPlatformRegion"},
|
||||||
{400, nullptr, "ActivateMigrationService"},
|
{400, nullptr, "ActivateMigrationService"},
|
||||||
@@ -74,17 +74,14 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_, std::shared_ptr<Ap
|
|||||||
{501, nullptr, "SuppressDisablingSleepTemporarily"},
|
{501, nullptr, "SuppressDisablingSleepTemporarily"},
|
||||||
{502, nullptr, "IsSleepEnabled"},
|
{502, nullptr, "IsSleepEnabled"},
|
||||||
{503, nullptr, "IsDisablingSleepSuppressed"},
|
{503, nullptr, "IsDisablingSleepSuppressed"},
|
||||||
{600, nullptr, "SetHidInputMagnificationForApplication"}, //20.0.0+
|
{600, nullptr, "Unknown600"}, //20.0.0+
|
||||||
{610, D<&ICommonStateGetter::Unknown610>, "Unknown610"}, //21.0.0+
|
{610, D<&ICommonStateGetter::Unknown610>, "Unknown610"}, //21.0.0+
|
||||||
{611, D<&ICommonStateGetter::Unknown611>, "Unknown611"}, //22.0.0+
|
{611, D<&ICommonStateGetter::Unknown611>, "Unknown611"}, //22.0.0+
|
||||||
{900, D<&ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled>, "SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled"}, //11.0.0+
|
{900, D<&ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled>, "SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled"}, //11.0.0+
|
||||||
{910, nullptr, "GetLaunchRequiredTick"}, //17.0.0+
|
{910, nullptr, "GetLaunchRequiredTick"}, //17.0.0+
|
||||||
{1000, D<&ICommonStateGetter::BeginVrMode3d>, "BeginVrMode3d"}, //19.0.0+
|
{1000, nullptr, "BeginVrMode3d"}, //19.0.0+
|
||||||
{1001, D<&ICommonStateGetter::EndVrMode3d>, "EndVrMode3d"}, //19.0.0+
|
{1001, nullptr, "EndVrMode3d"}, //19.0.0+
|
||||||
{1002, D<&ICommonStateGetter::IsVrModeEnabled3d>, "IsVrModeEnabled3d"}, //19.0.0+
|
{1002, nullptr, "IsVrModeEnabled3d"}, //19.0.0+
|
||||||
{1003, D<&ICommonStateGetter::GetVrLaboGoggleViewport>, "GetVrLaboGoggleViewport"}, //21.0.0+
|
|
||||||
{1004, D<&ICommonStateGetter::GetPanelPhysicalSizeForSpecificTitle>, "GetPanelPhysicalSizeForSpecificTitle"}, //21.0.0+
|
|
||||||
{1005, D<&ICommonStateGetter::GetPanelResolutionForSpecificTitle>, "GetPanelResolutionForSpecificTitle"}, //21.0.0+
|
|
||||||
};
|
};
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
@@ -314,12 +311,6 @@ Result ICommonStateGetter::PerformSystemButtonPressingIfInFocus(SystemButtonType
|
|||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ICommonStateGetter::EnableStartupLogoDisappearedMessage() {
|
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
||||||
m_applet->lifecycle_manager.PushUnorderedMessage(system.Kernel(), AppletMessage::StartupLogoDisappeared);
|
|
||||||
R_SUCCEED();
|
|
||||||
}
|
|
||||||
|
|
||||||
Result ICommonStateGetter::GetOperationModeSystemInfo(Out<u32> out_operation_mode_system_info) {
|
Result ICommonStateGetter::GetOperationModeSystemInfo(Out<u32> out_operation_mode_system_info) {
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
*out_operation_mode_system_info = 0;
|
*out_operation_mode_system_info = 0;
|
||||||
@@ -364,12 +355,6 @@ Result ICommonStateGetter::PushToGeneralChannel(SharedPointer<IStorage> storage)
|
|||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ICommonStateGetter::GetHomeButtonReaderLockAccessor(Out<SharedPointer<ILockAccessor>> out_lock_accessor) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
*out_lock_accessor = std::make_shared<ILockAccessor>(system);
|
|
||||||
R_SUCCEED();
|
|
||||||
}
|
|
||||||
|
|
||||||
Result ICommonStateGetter::SetHandlingHomeButtonShortPressedEnabled(bool enabled) {
|
Result ICommonStateGetter::SetHandlingHomeButtonShortPressedEnabled(bool enabled) {
|
||||||
LOG_DEBUG(Service_AM, "called, enabled={} applet_id={}", enabled, m_applet->applet_id);
|
LOG_DEBUG(Service_AM, "called, enabled={} applet_id={}", enabled, m_applet->applet_id);
|
||||||
|
|
||||||
@@ -378,58 +363,14 @@ Result ICommonStateGetter::SetHandlingHomeButtonShortPressedEnabled(bool enabled
|
|||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ICommonStateGetter::Unknown610(u64 unk) {
|
Result ICommonStateGetter::Unknown610() {
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ICommonStateGetter::Unknown611(u8 unk) {
|
Result ICommonStateGetter::Unknown611() {
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ICommonStateGetter::BeginVrMode3d() {
|
|
||||||
std::scoped_lock lk{m_applet->lock};
|
|
||||||
m_applet->vr_mode_enabled_3d = true;
|
|
||||||
LOG_WARNING(Service_AM, "VR Mode is {}", m_applet->vr_mode_enabled_3d ? "on" : "off");
|
|
||||||
R_SUCCEED();
|
|
||||||
}
|
|
||||||
|
|
||||||
Result ICommonStateGetter::EndVrMode3d() {
|
|
||||||
std::scoped_lock lk{m_applet->lock};
|
|
||||||
m_applet->vr_mode_enabled_3d = false;
|
|
||||||
LOG_WARNING(Service_AM, "VR Mode is {}", m_applet->vr_mode_enabled_3d ? "on" : "off");
|
|
||||||
R_SUCCEED();
|
|
||||||
}
|
|
||||||
|
|
||||||
Result ICommonStateGetter::IsVrModeEnabled3d(Out<bool> out_is_vr_mode_enabled_3d) {
|
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
||||||
std::scoped_lock lk{m_applet->lock};
|
|
||||||
*out_is_vr_mode_enabled_3d = m_applet->vr_mode_enabled_3d;
|
|
||||||
R_SUCCEED();
|
|
||||||
}
|
|
||||||
|
|
||||||
Result ICommonStateGetter::GetVrLaboGoggleViewport(Out<s32> out_x, Out<s32> out_y, Out<s32> out_width, Out<s32> out_height) {
|
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
||||||
*out_x = 0;
|
|
||||||
*out_y = 0;
|
|
||||||
*out_width = 1280;
|
|
||||||
*out_height = 720;
|
|
||||||
R_SUCCEED();
|
|
||||||
}
|
|
||||||
|
|
||||||
Result ICommonStateGetter::GetPanelPhysicalSizeForSpecificTitle(Out<f32> out_width, Out<f32> out_height) {
|
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
||||||
*out_width = 137250.0f / 1000.0f;
|
|
||||||
*out_height = 77200.0f / 1000.0f;
|
|
||||||
R_SUCCEED();
|
|
||||||
}
|
|
||||||
|
|
||||||
Result ICommonStateGetter::GetPanelResolutionForSpecificTitle(Out<s32> out_width, Out<s32> out_height) {
|
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
||||||
*out_width = 1280;
|
|
||||||
*out_height = 720;
|
|
||||||
R_SUCCEED();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Service::AM
|
} // namespace Service::AM
|
||||||
|
|||||||
@@ -56,23 +56,15 @@ private:
|
|||||||
Result GetDefaultDisplayResolution(Out<s32> out_width, Out<s32> out_height);
|
Result GetDefaultDisplayResolution(Out<s32> out_width, Out<s32> out_height);
|
||||||
Result GetBuiltInDisplayType(Out<s32> out_display_type);
|
Result GetBuiltInDisplayType(Out<s32> out_display_type);
|
||||||
Result PerformSystemButtonPressingIfInFocus(SystemButtonType type);
|
Result PerformSystemButtonPressingIfInFocus(SystemButtonType type);
|
||||||
Result EnableStartupLogoDisappearedMessage();
|
|
||||||
Result GetOperationModeSystemInfo(Out<u32> out_operation_mode_system_info);
|
Result GetOperationModeSystemInfo(Out<u32> out_operation_mode_system_info);
|
||||||
Result GetAppletLaunchedHistory(Out<s32> out_count,
|
Result GetAppletLaunchedHistory(Out<s32> out_count,
|
||||||
OutArray<AppletId, BufferAttr_HipcMapAlias> out_applet_ids);
|
OutArray<AppletId, BufferAttr_HipcMapAlias> out_applet_ids);
|
||||||
Result GetSettingsPlatformRegion(Out<Set::PlatformRegion> out_settings_platform_region);
|
Result GetSettingsPlatformRegion(Out<Set::PlatformRegion> out_settings_platform_region);
|
||||||
Result SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled();
|
Result SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled();
|
||||||
Result PushToGeneralChannel(SharedPointer<IStorage> storage); // cmd 20
|
Result PushToGeneralChannel(SharedPointer<IStorage> storage); // cmd 20
|
||||||
Result GetHomeButtonReaderLockAccessor(Out<SharedPointer<ILockAccessor>> out_lock_accessor);
|
|
||||||
Result SetHandlingHomeButtonShortPressedEnabled(bool enabled);
|
Result SetHandlingHomeButtonShortPressedEnabled(bool enabled);
|
||||||
Result Unknown610(u64 unk);
|
Result Unknown610();
|
||||||
Result Unknown611(u8 unk);
|
Result Unknown611();
|
||||||
Result BeginVrMode3d();
|
|
||||||
Result EndVrMode3d();
|
|
||||||
Result IsVrModeEnabled3d(Out<bool> out_is_vr_mode_enabled_3d);
|
|
||||||
Result GetVrLaboGoggleViewport(Out<s32> out_x, Out<s32> out_y, Out<s32> out_width, Out<s32> out_height);
|
|
||||||
Result GetPanelPhysicalSizeForSpecificTitle(Out<f32> out_width, Out<f32> out_height);
|
|
||||||
Result GetPanelResolutionForSpecificTitle(Out<s32> out_width, Out<s32> out_height);
|
|
||||||
|
|
||||||
void SetCpuBoostMode(HLERequestContext& ctx);
|
void SetCpuBoostMode(HLERequestContext& ctx);
|
||||||
|
|
||||||
|
|||||||
@@ -798,7 +798,7 @@ void LoopProcess(Core::System& system) {
|
|||||||
const auto FileSystemProxyFactory = [&] { return std::make_shared<FSP_SRV>(system); };
|
const auto FileSystemProxyFactory = [&] { return std::make_shared<FSP_SRV>(system); };
|
||||||
|
|
||||||
server_manager->RegisterNamedService("fsp-ldr", std::make_shared<FSP_LDR>(system));
|
server_manager->RegisterNamedService("fsp-ldr", std::make_shared<FSP_LDR>(system));
|
||||||
server_manager->RegisterNamedService("fsp-pr", std::make_shared<FSP_PR>(system));
|
server_manager->RegisterNamedService("fsp:pr", std::make_shared<FSP_PR>(system));
|
||||||
server_manager->RegisterNamedService("fsp-srv", std::move(FileSystemProxyFactory));
|
server_manager->RegisterNamedService("fsp-srv", std::move(FileSystemProxyFactory));
|
||||||
ServerManager::RunServer(std::move(server_manager));
|
ServerManager::RunServer(std::move(server_manager));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ public:
|
|||||||
RegisterHandlers(functions);
|
RegisterHandlers(functions);
|
||||||
}
|
}
|
||||||
~I2CSession() override = default;
|
~I2CSession() override = default;
|
||||||
|
|
||||||
Result Send(InBuffer<BufferAttr_HipcMapAlias> in_data, u32 transaction_option) {
|
Result Send(InBuffer<BufferAttr_HipcMapAlias> in_data, u32 transaction_option) {
|
||||||
LOG_WARNING(Service, "(stubbed) topt={}", transaction_option);
|
LOG_WARNING(Service, "(stubbed) topt={}", transaction_option);
|
||||||
R_THROW(ResultUnknown);
|
R_THROW(ResultUnknown);
|
||||||
@@ -49,40 +50,21 @@ public:
|
|||||||
: ServiceFramework{system_, "i2c"}
|
: ServiceFramework{system_, "i2c"}
|
||||||
{
|
{
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, C<&I2C::OpenSessionForDev>, "OpenSessionForDev"},
|
{0, nullptr, "OpenSessionForDev"},
|
||||||
{1, C<&I2C::OpenSession>, "OpenSession"},
|
{1, C<&I2C::OpenSession>, "OpenSession"},
|
||||||
{2, C<&I2C::HasDevice>, "HasDevice"},
|
{2, nullptr, "HasDevice"},
|
||||||
{3, C<&I2C::HasDeviceForDev>, "HasDeviceForDev"},
|
{3, nullptr, "HasDeviceForDev"},
|
||||||
{4, C<&I2C::OpenSession2>, "OpenSession2"},
|
{4, nullptr, "OpenSession2"},
|
||||||
};
|
};
|
||||||
RegisterHandlers(functions);
|
RegisterHandlers(functions);
|
||||||
}
|
}
|
||||||
~I2C() override = default;
|
~I2C() override = default;
|
||||||
Result OpenSessionForDev(OutInterface<I2CSession> out_session, s32 bus_idx, u32 slave_address, u32 addressing_mode, u32 speed_mode) {
|
|
||||||
|
Result OpenSession(I2CDevice device, OutInterface<I2CSession> out_session) {
|
||||||
LOG_DEBUG(Service, "(stubbed)");
|
LOG_DEBUG(Service, "(stubbed)");
|
||||||
*out_session = std::make_shared<I2CSession>(system);
|
*out_session = std::make_shared<I2CSession>(system);
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
Result OpenSession(OutInterface<I2CSession> out_session, I2CDevice device) {
|
|
||||||
LOG_DEBUG(Service, "(stubbed)");
|
|
||||||
*out_session = std::make_shared<I2CSession>(system);
|
|
||||||
R_SUCCEED();
|
|
||||||
}
|
|
||||||
Result HasDevice(Out<bool> out_has_device, I2CDevice device) {
|
|
||||||
LOG_DEBUG(Service, "(stubbed)");
|
|
||||||
*out_has_device = false;
|
|
||||||
R_SUCCEED();
|
|
||||||
}
|
|
||||||
Result HasDeviceForDev(Out<bool> out_has_device, I2CDevice device) {
|
|
||||||
LOG_DEBUG(Service, "(stubbed)");
|
|
||||||
*out_has_device = false;
|
|
||||||
R_SUCCEED();
|
|
||||||
}
|
|
||||||
Result OpenSession2(OutInterface<I2CSession> out_session, u32 device_code) {
|
|
||||||
LOG_DEBUG(Service, "(stubbed) device_code={}", device_code);
|
|
||||||
*out_session = std::make_shared<I2CSession>(system);
|
|
||||||
R_SUCCEED();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void LoopProcess(Core::System& system) {
|
void LoopProcess(Core::System& system) {
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
@@ -33,15 +30,15 @@ struct DeviceSettings {
|
|||||||
INSERT_PADDING_BYTES(0x20); // Reserved
|
INSERT_PADDING_BYTES(0x20); // Reserved
|
||||||
|
|
||||||
// nn::settings::system::ConsoleSixAxisSensorAccelerationBias
|
// nn::settings::system::ConsoleSixAxisSensorAccelerationBias
|
||||||
Common::Vec<f32, 3> console_six_axis_sensor_acceleration_bias;
|
Common::Vec3<f32> console_six_axis_sensor_acceleration_bias;
|
||||||
// nn::settings::system::ConsoleSixAxisSensorAngularVelocityBias
|
// nn::settings::system::ConsoleSixAxisSensorAngularVelocityBias
|
||||||
Common::Vec<f32, 3> console_six_axis_sensor_angular_velocity_bias;
|
Common::Vec3<f32> console_six_axis_sensor_angular_velocity_bias;
|
||||||
// nn::settings::system::ConsoleSixAxisSensorAccelerationGain
|
// nn::settings::system::ConsoleSixAxisSensorAccelerationGain
|
||||||
std::array<u8, 0x24> console_six_axis_sensor_acceleration_gain;
|
std::array<u8, 0x24> console_six_axis_sensor_acceleration_gain;
|
||||||
// nn::settings::system::ConsoleSixAxisSensorAngularVelocityGain
|
// nn::settings::system::ConsoleSixAxisSensorAngularVelocityGain
|
||||||
std::array<u8, 0x24> console_six_axis_sensor_angular_velocity_gain;
|
std::array<u8, 0x24> console_six_axis_sensor_angular_velocity_gain;
|
||||||
// nn::settings::system::ConsoleSixAxisSensorAngularVelocityTimeBias
|
// nn::settings::system::ConsoleSixAxisSensorAngularVelocityTimeBias
|
||||||
Common::Vec<f32, 3> console_six_axis_sensor_angular_velocity_time_bias;
|
Common::Vec3<f32> console_six_axis_sensor_angular_velocity_time_bias;
|
||||||
// nn::settings::system::ConsoleSixAxisSensorAngularAcceleration
|
// nn::settings::system::ConsoleSixAxisSensorAngularAcceleration
|
||||||
std::array<u8, 0x24> console_six_axis_sensor_angular_acceleration;
|
std::array<u8, 0x24> console_six_axis_sensor_angular_acceleration;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||||
@@ -153,15 +153,15 @@ struct SystemSettings {
|
|||||||
INSERT_PADDING_BYTES(0x7FF8); // Reserved
|
INSERT_PADDING_BYTES(0x7FF8); // Reserved
|
||||||
|
|
||||||
// nn::settings::system::ConsoleSixAxisSensorAccelerationBias
|
// nn::settings::system::ConsoleSixAxisSensorAccelerationBias
|
||||||
Common::Vec<f32, 3> console_six_axis_sensor_acceleration_bias;
|
Common::Vec3<f32> console_six_axis_sensor_acceleration_bias;
|
||||||
// nn::settings::system::ConsoleSixAxisSensorAngularVelocityBias
|
// nn::settings::system::ConsoleSixAxisSensorAngularVelocityBias
|
||||||
Common::Vec<f32, 3> console_six_axis_sensor_angular_velocity_bias;
|
Common::Vec3<f32> console_six_axis_sensor_angular_velocity_bias;
|
||||||
// nn::settings::system::ConsoleSixAxisSensorAccelerationGain
|
// nn::settings::system::ConsoleSixAxisSensorAccelerationGain
|
||||||
std::array<u8, 0x24> console_six_axis_sensor_acceleration_gain;
|
std::array<u8, 0x24> console_six_axis_sensor_acceleration_gain;
|
||||||
// nn::settings::system::ConsoleSixAxisSensorAngularVelocityGain
|
// nn::settings::system::ConsoleSixAxisSensorAngularVelocityGain
|
||||||
std::array<u8, 0x24> console_six_axis_sensor_angular_velocity_gain;
|
std::array<u8, 0x24> console_six_axis_sensor_angular_velocity_gain;
|
||||||
// nn::settings::system::ConsoleSixAxisSensorAngularVelocityTimeBias
|
// nn::settings::system::ConsoleSixAxisSensorAngularVelocityTimeBias
|
||||||
Common::Vec<f32, 3> console_six_axis_sensor_angular_velocity_time_bias;
|
Common::Vec3<f32> console_six_axis_sensor_angular_velocity_time_bias;
|
||||||
// nn::settings::system::ConsoleSixAxisSensorAngularAcceleration
|
// nn::settings::system::ConsoleSixAxisSensorAngularAcceleration
|
||||||
std::array<u8, 0x24> console_six_axis_sensor_angular_velocity_acceleration;
|
std::array<u8, 0x24> console_six_axis_sensor_angular_velocity_acceleration;
|
||||||
INSERT_PADDING_BYTES(0x70); // Reserved
|
INSERT_PADDING_BYTES(0x70); // Reserved
|
||||||
|
|||||||
@@ -13,7 +13,6 @@
|
|||||||
#include "core/hle/service/vi/manager_display_service.h"
|
#include "core/hle/service/vi/manager_display_service.h"
|
||||||
#include "core/hle/service/vi/system_display_service.h"
|
#include "core/hle/service/vi/system_display_service.h"
|
||||||
#include "core/hle/service/vi/vi_results.h"
|
#include "core/hle/service/vi/vi_results.h"
|
||||||
#include "service_creator.h"
|
|
||||||
|
|
||||||
namespace Service::VI {
|
namespace Service::VI {
|
||||||
|
|
||||||
@@ -39,7 +38,6 @@ IApplicationDisplayService::IApplicationDisplayService(Core::System& system_,
|
|||||||
{2031, C<&IApplicationDisplayService::DestroyStrayLayer>, "DestroyStrayLayer"},
|
{2031, C<&IApplicationDisplayService::DestroyStrayLayer>, "DestroyStrayLayer"},
|
||||||
{2101, C<&IApplicationDisplayService::SetLayerScalingMode>, "SetLayerScalingMode"},
|
{2101, C<&IApplicationDisplayService::SetLayerScalingMode>, "SetLayerScalingMode"},
|
||||||
{2102, C<&IApplicationDisplayService::ConvertScalingMode>, "ConvertScalingMode"},
|
{2102, C<&IApplicationDisplayService::ConvertScalingMode>, "ConvertScalingMode"},
|
||||||
{2103, C<&IApplicationDisplayService::Cmd2103>, "Cmd2103"},
|
|
||||||
{2450, C<&IApplicationDisplayService::GetIndirectLayerImageMap>, "GetIndirectLayerImageMap"},
|
{2450, C<&IApplicationDisplayService::GetIndirectLayerImageMap>, "GetIndirectLayerImageMap"},
|
||||||
{2451, nullptr, "GetIndirectLayerImageCropMap"},
|
{2451, nullptr, "GetIndirectLayerImageCropMap"},
|
||||||
{2460, C<&IApplicationDisplayService::GetIndirectLayerImageRequiredMemoryInfo>, "GetIndirectLayerImageRequiredMemoryInfo"},
|
{2460, C<&IApplicationDisplayService::GetIndirectLayerImageRequiredMemoryInfo>, "GetIndirectLayerImageRequiredMemoryInfo"},
|
||||||
@@ -291,11 +289,6 @@ Result IApplicationDisplayService::ConvertScalingMode(Out<ConvertedScaleMode> ou
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Result IApplicationDisplayService::Cmd2103(Out<std::array<u8, 0x18>> out_unk18) {
|
|
||||||
LOG_WARNING(Service_VI, "(stubbed)");
|
|
||||||
R_SUCCEED();
|
|
||||||
}
|
|
||||||
|
|
||||||
Result IApplicationDisplayService::GetIndirectLayerImageMap(
|
Result IApplicationDisplayService::GetIndirectLayerImageMap(
|
||||||
Out<u64> out_size, Out<u64> out_stride,
|
Out<u64> out_size, Out<u64> out_stride,
|
||||||
OutBuffer<BufferAttr_HipcMapTransferAllowsNonSecure | BufferAttr_HipcMapAlias> out_buffer,
|
OutBuffer<BufferAttr_HipcMapTransferAllowsNonSecure | BufferAttr_HipcMapAlias> out_buffer,
|
||||||
|
|||||||
@@ -64,7 +64,6 @@ public:
|
|||||||
Result GetDisplayVsyncEvent(OutCopyHandle<Kernel::KReadableEvent> out_vsync_event,
|
Result GetDisplayVsyncEvent(OutCopyHandle<Kernel::KReadableEvent> out_vsync_event,
|
||||||
u64 display_id);
|
u64 display_id);
|
||||||
Result ConvertScalingMode(Out<ConvertedScaleMode> out_scaling_mode, NintendoScaleMode mode);
|
Result ConvertScalingMode(Out<ConvertedScaleMode> out_scaling_mode, NintendoScaleMode mode);
|
||||||
Result Cmd2103(Out<std::array<u8, 0x18>> out_unk18);
|
|
||||||
Result GetIndirectLayerImageMap(
|
Result GetIndirectLayerImageMap(
|
||||||
Out<u64> out_size, Out<u64> out_stride,
|
Out<u64> out_size, Out<u64> out_stride,
|
||||||
OutBuffer<BufferAttr_HipcMapTransferAllowsNonSecure | BufferAttr_HipcMapAlias> out_buffer,
|
OutBuffer<BufferAttr_HipcMapTransferAllowsNonSecure | BufferAttr_HipcMapAlias> out_buffer,
|
||||||
|
|||||||
@@ -300,6 +300,28 @@ Result SharedBufferManager::CreateSession(Kernel::KProcess* owner_process, u64*
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Claim a presentation slot range.
|
||||||
|
u32 slot_base = 0;
|
||||||
|
|
||||||
|
std::array<bool, SharedBufferMaxSessions> in_use{};
|
||||||
|
for (const auto& [existing_aruid, existing] : m_sessions) {
|
||||||
|
const u32 index = existing.presentation_slot_base / SharedBufferSlotsPerSession;
|
||||||
|
|
||||||
|
if (index < in_use.size())
|
||||||
|
in_use[index] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 index = 0;
|
||||||
|
while (index < in_use.size() && in_use[index])
|
||||||
|
index++;
|
||||||
|
|
||||||
|
if (index >= in_use.size()) {
|
||||||
|
LOG_ERROR(Service_VI, "Out of shared buffer presentation slots ({} sessions)", SharedBufferMaxSessions);
|
||||||
|
R_THROW(VI::ResultOperationFailed);
|
||||||
|
}
|
||||||
|
|
||||||
|
slot_base = index * SharedBufferSlotsPerSession;
|
||||||
|
|
||||||
// Map into process.
|
// Map into process.
|
||||||
Common::ProcessAddress map_address{};
|
Common::ProcessAddress map_address{};
|
||||||
R_TRY(MapSharedBufferIntoProcessAddressSpace(std::addressof(map_address), m_buffer_page_group,
|
R_TRY(MapSharedBufferIntoProcessAddressSpace(std::addressof(map_address), m_buffer_page_group,
|
||||||
@@ -308,6 +330,7 @@ Result SharedBufferManager::CreateSession(Kernel::KProcess* owner_process, u64*
|
|||||||
// Create new session.
|
// Create new session.
|
||||||
auto [it, was_emplaced] = m_sessions.emplace(aruid, SharedBufferSession{});
|
auto [it, was_emplaced] = m_sessions.emplace(aruid, SharedBufferSession{});
|
||||||
auto& session = it->second;
|
auto& session = it->second;
|
||||||
|
session.presentation_slot_base = slot_base;
|
||||||
|
|
||||||
auto& container = m_nvdrv->GetContainer();
|
auto& container = m_nvdrv->GetContainer();
|
||||||
session.session_id = container.OpenSession(owner_process);
|
session.session_id = container.OpenSession(owner_process);
|
||||||
|
|||||||
@@ -39,16 +39,8 @@ Block::iterator Block::PrependNewInst(iterator insertion_point, Opcode opcode, s
|
|||||||
// just pool it!!! - reason why there is an inline buffer is because many small blocks are created
|
// just pool it!!! - reason why there is an inline buffer is because many small blocks are created
|
||||||
// with few instructions due to subpar optimisations on other passes... plus branch-heavy code will
|
// with few instructions due to subpar optimisations on other passes... plus branch-heavy code will
|
||||||
// hugely benefit from the coherency of faster allocations...
|
// hugely benefit from the coherency of faster allocations...
|
||||||
IR::Inst* inst;
|
inlined_inst.emplace_back(opcode);
|
||||||
if (inlined_inst.size() < inlined_inst.max_size()) {
|
auto* inst = &inlined_inst[inlined_inst.size() - 1];
|
||||||
inlined_inst.emplace_back(opcode);
|
|
||||||
inst = &inlined_inst[inlined_inst.size() - 1];
|
|
||||||
} else {
|
|
||||||
if (pooled_inst.empty() || pooled_inst.back().size() == pooled_inst.back().max_size())
|
|
||||||
pooled_inst.emplace_back();
|
|
||||||
pooled_inst.back().emplace_back(opcode);
|
|
||||||
inst = &pooled_inst.back()[pooled_inst.back().size() - 1];
|
|
||||||
}
|
|
||||||
DEBUG_ASSERT(args.size() == inst->NumArgs());
|
DEBUG_ASSERT(args.size() == inst->NumArgs());
|
||||||
std::for_each(args.begin(), args.end(), [&inst, index = size_t(0)](const auto& arg) mutable {
|
std::for_each(args.begin(), args.end(), [&inst, index = size_t(0)](const auto& arg) mutable {
|
||||||
inst->SetArg(index, arg);
|
inst->SetArg(index, arg);
|
||||||
@@ -61,7 +53,6 @@ void Block::Reset(LocationDescriptor location_) noexcept {
|
|||||||
mcl::intrusive_list<IR::Inst> tmp = {};
|
mcl::intrusive_list<IR::Inst> tmp = {};
|
||||||
instructions.swap(tmp);
|
instructions.swap(tmp);
|
||||||
inlined_inst.clear();
|
inlined_inst.clear();
|
||||||
pooled_inst.clear();
|
|
||||||
cond_failed.reset();
|
cond_failed.reset();
|
||||||
location = location_;
|
location = location_;
|
||||||
end_location = location_;
|
end_location = location_;
|
||||||
|
|||||||
@@ -142,11 +142,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// "Hot cache" for small blocks so we don't call global allocator
|
/// "Hot cache" for small blocks so we don't call global allocator
|
||||||
boost::container::static_vector<Inst, 30> inlined_inst;
|
boost::container::static_vector<Inst, 65536> inlined_inst = {};
|
||||||
/// List of instructions in this block.
|
/// List of instructions in this block.
|
||||||
instruction_list_type instructions;
|
instruction_list_type instructions;
|
||||||
/// "Long/far" memory pool
|
|
||||||
boost::container::stable_vector<boost::container::static_vector<Inst, 32>> pooled_inst;
|
|
||||||
/// Block to execute next if `cond` did not pass.
|
/// Block to execute next if `cond` did not pass.
|
||||||
std::optional<LocationDescriptor> cond_failed = {};
|
std::optional<LocationDescriptor> cond_failed = {};
|
||||||
/// Description of the starting location of this block
|
/// Description of the starting location of this block
|
||||||
@@ -162,7 +160,7 @@ public:
|
|||||||
/// Number of cycles this block takes to execute.
|
/// Number of cycles this block takes to execute.
|
||||||
size_t cycle_count = 0;
|
size_t cycle_count = 0;
|
||||||
};
|
};
|
||||||
static_assert(sizeof(Block) == 4096);
|
//static_assert(sizeof(Block) == 4096);
|
||||||
|
|
||||||
/// Returns a string representation of the contents of block. Intended for debugging.
|
/// Returns a string representation of the contents of block. Intended for debugging.
|
||||||
std::string DumpBlock(const IR::Block& block) noexcept;
|
std::string DumpBlock(const IR::Block& block) noexcept;
|
||||||
|
|||||||
@@ -299,17 +299,12 @@ void Config::ReadDataStorageValues() {
|
|||||||
void Config::ReadDebuggingValues() {
|
void Config::ReadDebuggingValues() {
|
||||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Debugging));
|
BeginGroup(Settings::TranslateCategory(Settings::Category::Debugging));
|
||||||
|
|
||||||
if (global) {
|
// Intentionally not using the QT default setting as this is intended to be changed in the ini
|
||||||
// Intentionally not using the QT default setting as this is intended to be changed in the ini
|
Settings::values.record_frame_times =
|
||||||
Settings::values.record_frame_times =
|
ReadBooleanSetting(std::string("record_frame_times"), std::make_optional(false));
|
||||||
ReadBooleanSetting(std::string("record_frame_times"), std::make_optional(false));
|
|
||||||
|
|
||||||
ReadCategory(Settings::Category::Debugging);
|
ReadCategory(Settings::Category::Debugging);
|
||||||
ReadCategory(Settings::Category::DebuggingGraphics);
|
ReadCategory(Settings::Category::DebuggingGraphics);
|
||||||
} else {
|
|
||||||
ReadSettingGeneric(&Settings::values.program_args);
|
|
||||||
ReadSettingGeneric(&Settings::values.debug_knobs);
|
|
||||||
}
|
|
||||||
|
|
||||||
EndGroup();
|
EndGroup();
|
||||||
}
|
}
|
||||||
@@ -420,12 +415,12 @@ void Config::ReadLibraryAppletValues() {
|
|||||||
void Config::ReadValues() {
|
void Config::ReadValues() {
|
||||||
if (global) {
|
if (global) {
|
||||||
ReadDataStorageValues();
|
ReadDataStorageValues();
|
||||||
|
ReadDebuggingValues();
|
||||||
ReadDisabledAddOnValues();
|
ReadDisabledAddOnValues();
|
||||||
ReadServiceValues();
|
ReadServiceValues();
|
||||||
ReadWebServiceValues();
|
ReadWebServiceValues();
|
||||||
ReadMiscellaneousValues();
|
ReadMiscellaneousValues();
|
||||||
}
|
}
|
||||||
ReadDebuggingValues();
|
|
||||||
ReadLibraryAppletValues();
|
ReadLibraryAppletValues();
|
||||||
ReadNetworkValues();
|
ReadNetworkValues();
|
||||||
ReadControlValues();
|
ReadControlValues();
|
||||||
@@ -516,13 +511,13 @@ void Config::SaveValues() {
|
|||||||
if (global) {
|
if (global) {
|
||||||
LOG_DEBUG(Config, "Saving global generic configuration values");
|
LOG_DEBUG(Config, "Saving global generic configuration values");
|
||||||
SaveDataStorageValues();
|
SaveDataStorageValues();
|
||||||
|
SaveDebuggingValues();
|
||||||
SaveDisabledAddOnValues();
|
SaveDisabledAddOnValues();
|
||||||
SaveWebServiceValues();
|
SaveWebServiceValues();
|
||||||
SaveMiscellaneousValues();
|
SaveMiscellaneousValues();
|
||||||
} else {
|
} else {
|
||||||
LOG_DEBUG(Config, "Saving only generic configuration values");
|
LOG_DEBUG(Config, "Saving only generic configuration values");
|
||||||
}
|
}
|
||||||
SaveDebuggingValues();
|
|
||||||
SaveLibraryAppletValues();
|
SaveLibraryAppletValues();
|
||||||
SaveNetworkValues();
|
SaveNetworkValues();
|
||||||
SaveControlValues();
|
SaveControlValues();
|
||||||
@@ -605,16 +600,11 @@ void Config::SaveDataStorageValues() {
|
|||||||
void Config::SaveDebuggingValues() {
|
void Config::SaveDebuggingValues() {
|
||||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Debugging));
|
BeginGroup(Settings::TranslateCategory(Settings::Category::Debugging));
|
||||||
|
|
||||||
if (global) {
|
// Intentionally not using the QT default setting as this is intended to be changed in the ini
|
||||||
// Intentionally not using the QT default setting as this is intended to be changed in the ini
|
WriteBooleanSetting(std::string("record_frame_times"), Settings::values.record_frame_times);
|
||||||
WriteBooleanSetting(std::string("record_frame_times"), Settings::values.record_frame_times);
|
|
||||||
|
|
||||||
WriteCategory(Settings::Category::Debugging);
|
WriteCategory(Settings::Category::Debugging);
|
||||||
WriteCategory(Settings::Category::DebuggingGraphics);
|
WriteCategory(Settings::Category::DebuggingGraphics);
|
||||||
} else {
|
|
||||||
WriteSettingGeneric(&Settings::values.program_args);
|
|
||||||
WriteSettingGeneric(&Settings::values.debug_knobs);
|
|
||||||
}
|
|
||||||
|
|
||||||
EndGroup();
|
EndGroup();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -170,12 +170,12 @@ void EmulatedConsole::SetMotion(const Common::Input::CallbackStatus& callback) {
|
|||||||
auto& emulated = console.motion_values.emulated;
|
auto& emulated = console.motion_values.emulated;
|
||||||
|
|
||||||
raw_status = TransformToMotion(callback);
|
raw_status = TransformToMotion(callback);
|
||||||
emulated.SetAcceleration(Common::Vec<f32, 3>{
|
emulated.SetAcceleration(Common::Vec3f{
|
||||||
raw_status.accel.x.value,
|
raw_status.accel.x.value,
|
||||||
raw_status.accel.y.value,
|
raw_status.accel.y.value,
|
||||||
raw_status.accel.z.value,
|
raw_status.accel.z.value,
|
||||||
});
|
});
|
||||||
emulated.SetGyroscope(Common::Vec<f32, 3>{
|
emulated.SetGyroscope(Common::Vec3f{
|
||||||
raw_status.gyro.x.value,
|
raw_status.gyro.x.value,
|
||||||
raw_status.gyro.y.value,
|
raw_status.gyro.y.value,
|
||||||
raw_status.gyro.z.value,
|
raw_status.gyro.z.value,
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include "common/input.h"
|
#include "common/input.h"
|
||||||
#include "common/param_package.h"
|
#include "common/param_package.h"
|
||||||
#include "common/point.h"
|
#include "common/point.h"
|
||||||
|
#include "common/quaternion.h"
|
||||||
#include "common/vector_math.h"
|
#include "common/vector_math.h"
|
||||||
#include "hid_core/frontend/motion_input.h"
|
#include "hid_core/frontend/motion_input.h"
|
||||||
#include "hid_core/hid_types.h"
|
#include "hid_core/hid_types.h"
|
||||||
@@ -42,12 +43,12 @@ using TouchValues = std::array<Common::Input::TouchStatus, MaxTouchDevices>;
|
|||||||
|
|
||||||
// Contains all motion related data that is used on the services
|
// Contains all motion related data that is used on the services
|
||||||
struct ConsoleMotion {
|
struct ConsoleMotion {
|
||||||
Common::Vec<f32, 3> accel{};
|
Common::Vec3f accel{};
|
||||||
Common::Vec<f32, 3> gyro{};
|
Common::Vec3f gyro{};
|
||||||
Common::Vec<f32, 3> rotation{};
|
Common::Vec3f rotation{};
|
||||||
std::array<Common::Vec<f32, 3>, 3> orientation{};
|
std::array<Common::Vec3f, 3> orientation{};
|
||||||
Common::Vec<f32, 4> quaternion{};
|
Common::Quaternion<f32> quaternion{};
|
||||||
Common::Vec<f32, 3> gyro_bias{};
|
Common::Vec3f gyro_bias{};
|
||||||
f32 verticalization_error{};
|
f32 verticalization_error{};
|
||||||
bool is_at_rest{};
|
bool is_at_rest{};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1051,12 +1051,12 @@ void EmulatedController::SetMotion(const Common::Input::CallbackStatus& callback
|
|||||||
auto& emulated = controller.motion_values[index].emulated;
|
auto& emulated = controller.motion_values[index].emulated;
|
||||||
|
|
||||||
raw_status = TransformToMotion(callback);
|
raw_status = TransformToMotion(callback);
|
||||||
emulated.SetAcceleration(Common::Vec<f32, 3>{
|
emulated.SetAcceleration(Common::Vec3f{
|
||||||
raw_status.accel.x.value,
|
raw_status.accel.x.value,
|
||||||
raw_status.accel.y.value,
|
raw_status.accel.y.value,
|
||||||
raw_status.accel.z.value,
|
raw_status.accel.z.value,
|
||||||
});
|
});
|
||||||
emulated.SetGyroscope(Common::Vec<f32, 3>{
|
emulated.SetGyroscope(Common::Vec3f{
|
||||||
raw_status.gyro.x.value,
|
raw_status.gyro.x.value,
|
||||||
raw_status.gyro.y.value,
|
raw_status.gyro.y.value,
|
||||||
raw_status.gyro.z.value,
|
raw_status.gyro.z.value,
|
||||||
|
|||||||
@@ -107,11 +107,11 @@ struct RingSensorForce {
|
|||||||
using NfcState = Common::Input::NfcStatus;
|
using NfcState = Common::Input::NfcStatus;
|
||||||
|
|
||||||
struct ControllerMotion {
|
struct ControllerMotion {
|
||||||
Common::Vec<f32, 3> accel{};
|
Common::Vec3f accel{};
|
||||||
Common::Vec<f32, 3> gyro{};
|
Common::Vec3f gyro{};
|
||||||
Common::Vec<f32, 3> rotation{};
|
Common::Vec3f rotation{};
|
||||||
Common::Vec<f32, 3> euler{};
|
Common::Vec3f euler{};
|
||||||
std::array<Common::Vec<f32, 3>, 3> orientation{};
|
std::array<Common::Vec3f, 3> orientation{};
|
||||||
bool is_at_rest{};
|
bool is_at_rest{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -26,19 +26,20 @@ void MotionInput::SetPID(f32 new_kp, f32 new_ki, f32 new_kd) {
|
|||||||
kd = new_kd;
|
kd = new_kd;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MotionInput::SetAcceleration(const Common::Vec<f32, 3>& acceleration) {
|
void MotionInput::SetAcceleration(const Common::Vec3f& acceleration) {
|
||||||
accel = acceleration;
|
accel = acceleration;
|
||||||
accel[0] = std::clamp(accel[0], -AccelMaxValue, AccelMaxValue);
|
|
||||||
accel[1] = std::clamp(accel[1], -AccelMaxValue, AccelMaxValue);
|
accel.x = std::clamp(accel.x, -AccelMaxValue, AccelMaxValue);
|
||||||
accel[2] = std::clamp(accel[2], -AccelMaxValue, AccelMaxValue);
|
accel.y = std::clamp(accel.y, -AccelMaxValue, AccelMaxValue);
|
||||||
|
accel.z = std::clamp(accel.z, -AccelMaxValue, AccelMaxValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MotionInput::SetGyroscope(const Common::Vec<f32, 3>& gyroscope) {
|
void MotionInput::SetGyroscope(const Common::Vec3f& gyroscope) {
|
||||||
gyro = gyroscope - gyro_bias;
|
gyro = gyroscope - gyro_bias;
|
||||||
|
|
||||||
gyro[0] = std::clamp(gyro[0], -GyroMaxValue, GyroMaxValue);
|
gyro.x = std::clamp(gyro.x, -GyroMaxValue, GyroMaxValue);
|
||||||
gyro[1] = std::clamp(gyro[1], -GyroMaxValue, GyroMaxValue);
|
gyro.y = std::clamp(gyro.y, -GyroMaxValue, GyroMaxValue);
|
||||||
gyro[2] = std::clamp(gyro[2], -GyroMaxValue, GyroMaxValue);
|
gyro.z = std::clamp(gyro.z, -GyroMaxValue, GyroMaxValue);
|
||||||
|
|
||||||
// Auto adjust gyro_bias to minimize drift
|
// Auto adjust gyro_bias to minimize drift
|
||||||
if (!IsMoving(IsAtRestRelaxed)) {
|
if (!IsMoving(IsAtRestRelaxed)) {
|
||||||
@@ -58,25 +59,25 @@ void MotionInput::SetGyroscope(const Common::Vec<f32, 3>& gyroscope) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MotionInput::SetQuaternion(const Common::Vec<f32, 4>& quaternion) {
|
void MotionInput::SetQuaternion(const Common::Quaternion<f32>& quaternion) {
|
||||||
quat = quaternion;
|
quat = quaternion;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MotionInput::SetEulerAngles(const Common::Vec<f32, 3>& euler_angles) {
|
void MotionInput::SetEulerAngles(const Common::Vec3f& euler_angles) {
|
||||||
const float cr = std::cos(euler_angles[0] * 0.5f);
|
const float cr = std::cos(euler_angles.x * 0.5f);
|
||||||
const float sr = std::sin(euler_angles[0] * 0.5f);
|
const float sr = std::sin(euler_angles.x * 0.5f);
|
||||||
const float cp = std::cos(euler_angles[1] * 0.5f);
|
const float cp = std::cos(euler_angles.y * 0.5f);
|
||||||
const float sp = std::sin(euler_angles[1] * 0.5f);
|
const float sp = std::sin(euler_angles.y * 0.5f);
|
||||||
const float cy = std::cos(euler_angles[2] * 0.5f);
|
const float cy = std::cos(euler_angles.z * 0.5f);
|
||||||
const float sy = std::sin(euler_angles[2] * 0.5f);
|
const float sy = std::sin(euler_angles.z * 0.5f);
|
||||||
|
|
||||||
quat[3] = cr * cp * cy + sr * sp * sy;
|
quat.w = cr * cp * cy + sr * sp * sy;
|
||||||
quat[0] = sr * cp * cy - cr * sp * sy;
|
quat.xyz.x = sr * cp * cy - cr * sp * sy;
|
||||||
quat[1] = cr * sp * cy + sr * cp * sy;
|
quat.xyz.y = cr * sp * cy + sr * cp * sy;
|
||||||
quat[2] = cr * cp * sy - sr * sp * cy;
|
quat.xyz.z = cr * cp * sy - sr * sp * cy;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MotionInput::SetGyroBias(const Common::Vec<f32, 3>& bias) {
|
void MotionInput::SetGyroBias(const Common::Vec3f& bias) {
|
||||||
gyro_bias = bias;
|
gyro_bias = bias;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,7 +98,7 @@ void MotionInput::ResetRotations() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MotionInput::ResetQuaternion() {
|
void MotionInput::ResetQuaternion() {
|
||||||
quat = Common::Vec<f32, 4>{0.0f, 0.0f, -1.0f, 0.0f};
|
quat = {{0.0f, 0.0f, -1.0f}, 0.0f};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MotionInput::IsMoving(f32 sensitivity) const {
|
bool MotionInput::IsMoving(f32 sensitivity) const {
|
||||||
@@ -136,10 +137,10 @@ void MotionInput::UpdateOrientation(u64 elapsed_time) {
|
|||||||
ResetOrientation();
|
ResetOrientation();
|
||||||
}
|
}
|
||||||
// Short name local variable for readability
|
// Short name local variable for readability
|
||||||
f32 q1 = quat[3];
|
f32 q1 = quat.w;
|
||||||
f32 q2 = quat[0];
|
f32 q2 = quat.xyz[0];
|
||||||
f32 q3 = quat[1];
|
f32 q3 = quat.xyz[1];
|
||||||
f32 q4 = quat[2];
|
f32 q4 = quat.xyz[2];
|
||||||
const auto sample_period = static_cast<f32>(elapsed_time) / 1000000.0f;
|
const auto sample_period = static_cast<f32>(elapsed_time) / 1000000.0f;
|
||||||
|
|
||||||
// Ignore invalid elapsed time
|
// Ignore invalid elapsed time
|
||||||
@@ -149,23 +150,23 @@ void MotionInput::UpdateOrientation(u64 elapsed_time) {
|
|||||||
|
|
||||||
const auto normal_accel = accel.Normalized();
|
const auto normal_accel = accel.Normalized();
|
||||||
auto rad_gyro = gyro * std::numbers::pi_v<float> * 2.f;
|
auto rad_gyro = gyro * std::numbers::pi_v<float> * 2.f;
|
||||||
const f32 swap = rad_gyro[0];
|
const f32 swap = rad_gyro.x;
|
||||||
rad_gyro[0] = rad_gyro[1];
|
rad_gyro.x = rad_gyro.y;
|
||||||
rad_gyro[1] = -swap;
|
rad_gyro.y = -swap;
|
||||||
rad_gyro[2] = -rad_gyro[2];
|
rad_gyro.z = -rad_gyro.z;
|
||||||
|
|
||||||
// Clear gyro values if there is no gyro present
|
// Clear gyro values if there is no gyro present
|
||||||
if (only_accelerometer) {
|
if (only_accelerometer) {
|
||||||
rad_gyro[0] = 0;
|
rad_gyro.x = 0;
|
||||||
rad_gyro[1] = 0;
|
rad_gyro.y = 0;
|
||||||
rad_gyro[2] = 0;
|
rad_gyro.z = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ignore drift correction if acceleration is not reliable
|
// Ignore drift correction if acceleration is not reliable
|
||||||
if (accel.Length() >= 0.75f && accel.Length() <= 1.25f) {
|
if (accel.Length() >= 0.75f && accel.Length() <= 1.25f) {
|
||||||
const f32 ax = -normal_accel[0];
|
const f32 ax = -normal_accel.x;
|
||||||
const f32 ay = normal_accel[1];
|
const f32 ay = normal_accel.y;
|
||||||
const f32 az = -normal_accel[2];
|
const f32 az = -normal_accel.z;
|
||||||
|
|
||||||
// Estimated direction of gravity
|
// Estimated direction of gravity
|
||||||
const f32 vx = 2.0f * (q2 * q4 - q1 * q3);
|
const f32 vx = 2.0f * (q2 * q4 - q1 * q3);
|
||||||
@@ -173,7 +174,7 @@ void MotionInput::UpdateOrientation(u64 elapsed_time) {
|
|||||||
const f32 vz = q1 * q1 - q2 * q2 - q3 * q3 + q4 * q4;
|
const f32 vz = q1 * q1 - q2 * q2 - q3 * q3 + q4 * q4;
|
||||||
|
|
||||||
// Error is cross product between estimated direction and measured direction of gravity
|
// Error is cross product between estimated direction and measured direction of gravity
|
||||||
const Common::Vec<f32, 3> new_real_error{
|
const Common::Vec3f new_real_error = {
|
||||||
az * vx - ax * vz,
|
az * vx - ax * vz,
|
||||||
ay * vz - az * vy,
|
ay * vz - az * vy,
|
||||||
ax * vy - ay * vx,
|
ax * vy - ay * vx,
|
||||||
@@ -201,16 +202,16 @@ void MotionInput::UpdateOrientation(u64 elapsed_time) {
|
|||||||
rad_gyro += 10.0f * kd * derivative_error;
|
rad_gyro += 10.0f * kd * derivative_error;
|
||||||
|
|
||||||
// Emulate gyro values for games that need them
|
// Emulate gyro values for games that need them
|
||||||
gyro[0] = -rad_gyro[1];
|
gyro.x = -rad_gyro.y;
|
||||||
gyro[1] = rad_gyro[0];
|
gyro.y = rad_gyro.x;
|
||||||
gyro[2] = -rad_gyro[2];
|
gyro.z = -rad_gyro.z;
|
||||||
UpdateRotation(elapsed_time);
|
UpdateRotation(elapsed_time);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const f32 gx = rad_gyro[1];
|
const f32 gx = rad_gyro.y;
|
||||||
const f32 gy = rad_gyro[0];
|
const f32 gy = rad_gyro.x;
|
||||||
const f32 gz = rad_gyro[2];
|
const f32 gz = rad_gyro.z;
|
||||||
|
|
||||||
// Integrate rate of change of quaternion
|
// Integrate rate of change of quaternion
|
||||||
const f32 pa = q2;
|
const f32 pa = q2;
|
||||||
@@ -221,58 +222,57 @@ void MotionInput::UpdateOrientation(u64 elapsed_time) {
|
|||||||
q3 = pb + (q1 * gy - pa * gz + pc * gx) * (0.5f * sample_period);
|
q3 = pb + (q1 * gy - pa * gz + pc * gx) * (0.5f * sample_period);
|
||||||
q4 = pc + (q1 * gz + pa * gy - pb * gx) * (0.5f * sample_period);
|
q4 = pc + (q1 * gz + pa * gy - pb * gx) * (0.5f * sample_period);
|
||||||
|
|
||||||
quat[3] = q1;
|
quat.w = q1;
|
||||||
quat[0] = q2;
|
quat.xyz[0] = q2;
|
||||||
quat[1] = q3;
|
quat.xyz[1] = q3;
|
||||||
quat[2] = q4;
|
quat.xyz[2] = q4;
|
||||||
quat = quat.Normalized();
|
quat = quat.Normalized();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::array<Common::Vec<f32, 3>, 3> MotionInput::GetOrientation() const {
|
std::array<Common::Vec3f, 3> MotionInput::GetOrientation() const {
|
||||||
const Common::Vec<f32, 4> quad{
|
const Common::Quaternion<float> quad{
|
||||||
-quat[1],
|
.xyz = {-quat.xyz[1], -quat.xyz[0], -quat.w},
|
||||||
-quat[0],
|
.w = -quat.xyz[2],
|
||||||
-quat[3],
|
|
||||||
-quat[2],
|
|
||||||
};
|
};
|
||||||
const std::array<f32, 16> matrix4x4 = quad.ToMatrix();
|
const std::array<float, 16> matrix4x4 = quad.ToMatrix();
|
||||||
return {Common::Vec<f32, 3>(matrix4x4[0], matrix4x4[1], -matrix4x4[2]),
|
|
||||||
Common::Vec<f32, 3>(matrix4x4[4], matrix4x4[5], -matrix4x4[6]),
|
return {Common::Vec3f(matrix4x4[0], matrix4x4[1], -matrix4x4[2]),
|
||||||
Common::Vec<f32, 3>(-matrix4x4[8], -matrix4x4[9], matrix4x4[10])};
|
Common::Vec3f(matrix4x4[4], matrix4x4[5], -matrix4x4[6]),
|
||||||
|
Common::Vec3f(-matrix4x4[8], -matrix4x4[9], matrix4x4[10])};
|
||||||
}
|
}
|
||||||
|
|
||||||
Common::Vec<f32, 3> MotionInput::GetAcceleration() const {
|
Common::Vec3f MotionInput::GetAcceleration() const {
|
||||||
return accel;
|
return accel;
|
||||||
}
|
}
|
||||||
|
|
||||||
Common::Vec<f32, 3> MotionInput::GetGyroscope() const {
|
Common::Vec3f MotionInput::GetGyroscope() const {
|
||||||
return gyro;
|
return gyro;
|
||||||
}
|
}
|
||||||
|
|
||||||
Common::Vec<f32, 3> MotionInput::GetGyroBias() const {
|
Common::Vec3f MotionInput::GetGyroBias() const {
|
||||||
return gyro_bias;
|
return gyro_bias;
|
||||||
}
|
}
|
||||||
|
|
||||||
Common::Vec<f32, 4> MotionInput::GetQuaternion() const {
|
Common::Quaternion<f32> MotionInput::GetQuaternion() const {
|
||||||
return quat;
|
return quat;
|
||||||
}
|
}
|
||||||
|
|
||||||
Common::Vec<f32, 3> MotionInput::GetRotations() const {
|
Common::Vec3f MotionInput::GetRotations() const {
|
||||||
return rotations;
|
return rotations;
|
||||||
}
|
}
|
||||||
|
|
||||||
Common::Vec<f32, 3> MotionInput::GetEulerAngles() const {
|
Common::Vec3f MotionInput::GetEulerAngles() const {
|
||||||
// roll (x-axis rotation)
|
// roll (x-axis rotation)
|
||||||
const float sinr_cosp = 2 * (quat[3] * quat[0] + quat[1] * quat[2]);
|
const float sinr_cosp = 2 * (quat.w * quat.xyz.x + quat.xyz.y * quat.xyz.z);
|
||||||
const float cosr_cosp = 1 - 2 * (quat[0] * quat[0] + quat[1] * quat[1]);
|
const float cosr_cosp = 1 - 2 * (quat.xyz.x * quat.xyz.x + quat.xyz.y * quat.xyz.y);
|
||||||
|
|
||||||
// pitch (y-axis rotation)
|
// pitch (y-axis rotation)
|
||||||
const float sinp = std::sqrt(1 + 2 * (quat[3] * quat[1] - quat[0] * quat[2]));
|
const float sinp = std::sqrt(1 + 2 * (quat.w * quat.xyz.y - quat.xyz.x * quat.xyz.z));
|
||||||
const float cosp = std::sqrt(1 - 2 * (quat[3] * quat[1] - quat[0] * quat[2]));
|
const float cosp = std::sqrt(1 - 2 * (quat.w * quat.xyz.y - quat.xyz.x * quat.xyz.z));
|
||||||
|
|
||||||
// yaw (z-axis rotation)
|
// yaw (z-axis rotation)
|
||||||
const float siny_cosp = 2 * (quat[3] * quat[2] + quat[0] * quat[1]);
|
const float siny_cosp = 2 * (quat.w * quat.xyz.z + quat.xyz.x * quat.xyz.y);
|
||||||
const float cosy_cosp = 1 - 2 * (quat[1] * quat[1] + quat[2] * quat[2]);
|
const float cosy_cosp = 1 - 2 * (quat.xyz.y * quat.xyz.y + quat.xyz.z * quat.xyz.z);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
std::atan2(sinr_cosp, cosr_cosp),
|
std::atan2(sinr_cosp, cosr_cosp),
|
||||||
@@ -285,13 +285,13 @@ void MotionInput::ResetOrientation() {
|
|||||||
if (!reset_enabled || only_accelerometer) {
|
if (!reset_enabled || only_accelerometer) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!IsMoving(IsAtRestRelaxed) && accel[2] <= -0.9f) {
|
if (!IsMoving(IsAtRestRelaxed) && accel.z <= -0.9f) {
|
||||||
++reset_counter;
|
++reset_counter;
|
||||||
if (reset_counter > 900) {
|
if (reset_counter > 900) {
|
||||||
quat[3] = 0;
|
quat.w = 0;
|
||||||
quat[0] = 0;
|
quat.xyz[0] = 0;
|
||||||
quat[1] = 0;
|
quat.xyz[1] = 0;
|
||||||
quat[2] = -1;
|
quat.xyz[2] = -1;
|
||||||
SetOrientationFromAccelerometer();
|
SetOrientationFromAccelerometer();
|
||||||
integral_error = {};
|
integral_error = {};
|
||||||
reset_counter = 0;
|
reset_counter = 0;
|
||||||
@@ -309,15 +309,15 @@ void MotionInput::SetOrientationFromAccelerometer() {
|
|||||||
|
|
||||||
while (!IsCalibrated(0.01f) && ++iterations < 100) {
|
while (!IsCalibrated(0.01f) && ++iterations < 100) {
|
||||||
// Short name local variable for readability
|
// Short name local variable for readability
|
||||||
f32 q1 = quat[3];
|
f32 q1 = quat.w;
|
||||||
f32 q2 = quat[0];
|
f32 q2 = quat.xyz[0];
|
||||||
f32 q3 = quat[1];
|
f32 q3 = quat.xyz[1];
|
||||||
f32 q4 = quat[2];
|
f32 q4 = quat.xyz[2];
|
||||||
|
|
||||||
Common::Vec<f32, 3> rad_gyro;
|
Common::Vec3f rad_gyro;
|
||||||
const f32 ax = -normal_accel[0];
|
const f32 ax = -normal_accel.x;
|
||||||
const f32 ay = normal_accel[1];
|
const f32 ay = normal_accel.y;
|
||||||
const f32 az = -normal_accel[2];
|
const f32 az = -normal_accel.z;
|
||||||
|
|
||||||
// Estimated direction of gravity
|
// Estimated direction of gravity
|
||||||
const f32 vx = 2.0f * (q2 * q4 - q1 * q3);
|
const f32 vx = 2.0f * (q2 * q4 - q1 * q3);
|
||||||
@@ -325,7 +325,7 @@ void MotionInput::SetOrientationFromAccelerometer() {
|
|||||||
const f32 vz = q1 * q1 - q2 * q2 - q3 * q3 + q4 * q4;
|
const f32 vz = q1 * q1 - q2 * q2 - q3 * q3 + q4 * q4;
|
||||||
|
|
||||||
// Error is cross product between estimated direction and measured direction of gravity
|
// Error is cross product between estimated direction and measured direction of gravity
|
||||||
const Common::Vec<f32, 3> new_real_error = {
|
const Common::Vec3f new_real_error = {
|
||||||
az * vx - ax * vz,
|
az * vx - ax * vz,
|
||||||
ay * vz - az * vy,
|
ay * vz - az * vy,
|
||||||
ax * vy - ay * vx,
|
ax * vy - ay * vx,
|
||||||
@@ -338,9 +338,9 @@ void MotionInput::SetOrientationFromAccelerometer() {
|
|||||||
rad_gyro += 5.0f * ki * integral_error;
|
rad_gyro += 5.0f * ki * integral_error;
|
||||||
rad_gyro += 10.0f * kd * derivative_error;
|
rad_gyro += 10.0f * kd * derivative_error;
|
||||||
|
|
||||||
const f32 gx = rad_gyro[1];
|
const f32 gx = rad_gyro.y;
|
||||||
const f32 gy = rad_gyro[0];
|
const f32 gy = rad_gyro.x;
|
||||||
const f32 gz = rad_gyro[2];
|
const f32 gz = rad_gyro.z;
|
||||||
|
|
||||||
// Integrate rate of change of quaternion
|
// Integrate rate of change of quaternion
|
||||||
const f32 pa = q2;
|
const f32 pa = q2;
|
||||||
@@ -351,10 +351,10 @@ void MotionInput::SetOrientationFromAccelerometer() {
|
|||||||
q3 = pb + (q1 * gy - pa * gz + pc * gx) * (0.5f * sample_period);
|
q3 = pb + (q1 * gy - pa * gz + pc * gx) * (0.5f * sample_period);
|
||||||
q4 = pc + (q1 * gz + pa * gy - pb * gx) * (0.5f * sample_period);
|
q4 = pc + (q1 * gz + pa * gy - pb * gx) * (0.5f * sample_period);
|
||||||
|
|
||||||
quat[3] = q1;
|
quat.w = q1;
|
||||||
quat[0] = q2;
|
quat.xyz[0] = q2;
|
||||||
quat[1] = q3;
|
quat.xyz[1] = q3;
|
||||||
quat[2] = q4;
|
quat.xyz[2] = q4;
|
||||||
quat = quat.Normalized();
|
quat = quat.Normalized();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
#include "common/quaternion.h"
|
||||||
#include "common/vector_math.h"
|
#include "common/vector_math.h"
|
||||||
|
|
||||||
namespace Core::HID {
|
namespace Core::HID {
|
||||||
@@ -36,11 +34,11 @@ public:
|
|||||||
MotionInput& operator=(MotionInput&&) = default;
|
MotionInput& operator=(MotionInput&&) = default;
|
||||||
|
|
||||||
void SetPID(f32 new_kp, f32 new_ki, f32 new_kd);
|
void SetPID(f32 new_kp, f32 new_ki, f32 new_kd);
|
||||||
void SetAcceleration(const Common::Vec<f32, 3>& acceleration);
|
void SetAcceleration(const Common::Vec3f& acceleration);
|
||||||
void SetGyroscope(const Common::Vec<f32, 3>& gyroscope);
|
void SetGyroscope(const Common::Vec3f& gyroscope);
|
||||||
void SetQuaternion(const Common::Vec<f32, 4>& quaternion);
|
void SetQuaternion(const Common::Quaternion<f32>& quaternion);
|
||||||
void SetEulerAngles(const Common::Vec<f32, 3>& euler_angles);
|
void SetEulerAngles(const Common::Vec3f& euler_angles);
|
||||||
void SetGyroBias(const Common::Vec<f32, 3>& bias);
|
void SetGyroBias(const Common::Vec3f& bias);
|
||||||
void SetGyroThreshold(f32 threshold);
|
void SetGyroThreshold(f32 threshold);
|
||||||
|
|
||||||
/// Applies a modifier on top of the normal gyro threshold
|
/// Applies a modifier on top of the normal gyro threshold
|
||||||
@@ -55,13 +53,13 @@ public:
|
|||||||
|
|
||||||
void Calibrate();
|
void Calibrate();
|
||||||
|
|
||||||
[[nodiscard]] std::array<Common::Vec<f32, 3>, 3> GetOrientation() const;
|
[[nodiscard]] std::array<Common::Vec3f, 3> GetOrientation() const;
|
||||||
[[nodiscard]] Common::Vec<f32, 3> GetAcceleration() const;
|
[[nodiscard]] Common::Vec3f GetAcceleration() const;
|
||||||
[[nodiscard]] Common::Vec<f32, 3> GetGyroscope() const;
|
[[nodiscard]] Common::Vec3f GetGyroscope() const;
|
||||||
[[nodiscard]] Common::Vec<f32, 3> GetGyroBias() const;
|
[[nodiscard]] Common::Vec3f GetGyroBias() const;
|
||||||
[[nodiscard]] Common::Vec<f32, 3> GetRotations() const;
|
[[nodiscard]] Common::Vec3f GetRotations() const;
|
||||||
[[nodiscard]] Common::Vec<f32, 4> GetQuaternion() const;
|
[[nodiscard]] Common::Quaternion<f32> GetQuaternion() const;
|
||||||
[[nodiscard]] Common::Vec<f32, 3> GetEulerAngles() const;
|
[[nodiscard]] Common::Vec3f GetEulerAngles() const;
|
||||||
|
|
||||||
[[nodiscard]] bool IsMoving(f32 sensitivity) const;
|
[[nodiscard]] bool IsMoving(f32 sensitivity) const;
|
||||||
[[nodiscard]] bool IsCalibrated(f32 sensitivity) const;
|
[[nodiscard]] bool IsCalibrated(f32 sensitivity) const;
|
||||||
@@ -77,24 +75,24 @@ private:
|
|||||||
f32 kd;
|
f32 kd;
|
||||||
|
|
||||||
// PID errors
|
// PID errors
|
||||||
Common::Vec<f32, 3> real_error;
|
Common::Vec3f real_error;
|
||||||
Common::Vec<f32, 3> integral_error;
|
Common::Vec3f integral_error;
|
||||||
Common::Vec<f32, 3> derivative_error;
|
Common::Vec3f derivative_error;
|
||||||
|
|
||||||
// Quaternion containing the device orientation
|
// Quaternion containing the device orientation
|
||||||
Common::Vec<f32, 4> quat;
|
Common::Quaternion<f32> quat;
|
||||||
|
|
||||||
// Number of full rotations in each axis
|
// Number of full rotations in each axis
|
||||||
Common::Vec<f32, 3> rotations;
|
Common::Vec3f rotations;
|
||||||
|
|
||||||
// Acceleration vector measurement in G force
|
// Acceleration vector measurement in G force
|
||||||
Common::Vec<f32, 3> accel;
|
Common::Vec3f accel;
|
||||||
|
|
||||||
// Gyroscope vector measurement in radians/s.
|
// Gyroscope vector measurement in radians/s.
|
||||||
Common::Vec<f32, 3> gyro;
|
Common::Vec3f gyro;
|
||||||
|
|
||||||
// Vector to be subtracted from gyro measurements
|
// Vector to be subtracted from gyro measurements
|
||||||
Common::Vec<f32, 3> gyro_bias;
|
Common::Vec3f gyro_bias;
|
||||||
|
|
||||||
// Minimum gyro amplitude to detect if the device is moving
|
// Minimum gyro amplitude to detect if the device is moving
|
||||||
f32 gyro_threshold = 0.0f;
|
f32 gyro_threshold = 0.0f;
|
||||||
|
|||||||
@@ -609,10 +609,10 @@ static_assert(sizeof(SixAxisSensorAttribute) == 4, "SixAxisSensorAttribute is an
|
|||||||
struct SixAxisSensorState {
|
struct SixAxisSensorState {
|
||||||
s64 delta_time{};
|
s64 delta_time{};
|
||||||
s64 sampling_number{};
|
s64 sampling_number{};
|
||||||
Common::Vec<f32, 3> accel{};
|
Common::Vec3f accel{};
|
||||||
Common::Vec<f32, 3> gyro{};
|
Common::Vec3f gyro{};
|
||||||
Common::Vec<f32, 3> rotation{};
|
Common::Vec3f rotation{};
|
||||||
std::array<Common::Vec<f32, 3>, 3> orientation{};
|
std::array<Common::Vec3f, 3> orientation{};
|
||||||
SixAxisSensorAttribute attribute{};
|
SixAxisSensorAttribute attribute{};
|
||||||
INSERT_PADDING_BYTES(4); // Reserved
|
INSERT_PADDING_BYTES(4); // Reserved
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
@@ -196,7 +196,7 @@ struct ConsoleSixAxisSensorSharedMemoryFormat {
|
|||||||
bool is_seven_six_axis_sensor_at_rest{};
|
bool is_seven_six_axis_sensor_at_rest{};
|
||||||
INSERT_PADDING_BYTES(3); // padding
|
INSERT_PADDING_BYTES(3); // padding
|
||||||
f32 verticalization_error{};
|
f32 verticalization_error{};
|
||||||
Common::Vec<f32, 3> gyro_bias{};
|
Common::Vec3f gyro_bias{};
|
||||||
INSERT_PADDING_BYTES(4); // padding
|
INSERT_PADDING_BYTES(4); // padding
|
||||||
};
|
};
|
||||||
static_assert(sizeof(ConsoleSixAxisSensorSharedMemoryFormat) == 0x20,
|
static_assert(sizeof(ConsoleSixAxisSensorSharedMemoryFormat) == 0x20,
|
||||||
|
|||||||
@@ -46,11 +46,14 @@ void SevenSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
|
|||||||
next_seven_sixaxis_state.accel = motion_status.accel;
|
next_seven_sixaxis_state.accel = motion_status.accel;
|
||||||
next_seven_sixaxis_state.gyro = motion_status.gyro;
|
next_seven_sixaxis_state.gyro = motion_status.gyro;
|
||||||
next_seven_sixaxis_state.quaternion = {
|
next_seven_sixaxis_state.quaternion = {
|
||||||
motion_status.quaternion[1],
|
{
|
||||||
motion_status.quaternion[0],
|
motion_status.quaternion.xyz.y,
|
||||||
-motion_status.quaternion[3],
|
motion_status.quaternion.xyz.x,
|
||||||
-motion_status.quaternion[2],
|
-motion_status.quaternion.w,
|
||||||
|
},
|
||||||
|
-motion_status.quaternion.xyz.z,
|
||||||
};
|
};
|
||||||
|
|
||||||
seven_sixaxis_lifo.WriteNextEntry(next_seven_sixaxis_state);
|
seven_sixaxis_lifo.WriteNextEntry(next_seven_sixaxis_state);
|
||||||
transfer_memory_owner->GetMemory().WriteBlock(transfer_memory, &seven_sixaxis_lifo,
|
transfer_memory_owner->GetMemory().WriteBlock(transfer_memory, &seven_sixaxis_lifo,
|
||||||
sizeof(seven_sixaxis_lifo));
|
sizeof(seven_sixaxis_lifo));
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/vector_math.h"
|
#include "common/quaternion.h"
|
||||||
#include "common/typed_address.h"
|
#include "common/typed_address.h"
|
||||||
#include "hid_core/resources/controller_base.h"
|
#include "hid_core/resources/controller_base.h"
|
||||||
#include "hid_core/resources/ring_lifo.h"
|
#include "hid_core/resources/ring_lifo.h"
|
||||||
@@ -51,9 +51,9 @@ private:
|
|||||||
u64 timestamp{};
|
u64 timestamp{};
|
||||||
u64 sampling_number{};
|
u64 sampling_number{};
|
||||||
u64 unknown{};
|
u64 unknown{};
|
||||||
Common::Vec<f32, 3> accel{};
|
Common::Vec3f accel{};
|
||||||
Common::Vec<f32, 3> gyro{};
|
Common::Vec3f gyro{};
|
||||||
Common::Vec<f32, 4> quaternion{};
|
Common::Quaternion<f32> quaternion{};
|
||||||
};
|
};
|
||||||
static_assert(sizeof(SevenSixAxisState) == 0x48, "SevenSixAxisState is an invalid size");
|
static_assert(sizeof(SevenSixAxisState) == 0x48, "SevenSixAxisState is an invalid size");
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
@@ -96,9 +93,9 @@ void SixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
|
|||||||
.accel = {0, 0, -1.0f},
|
.accel = {0, 0, -1.0f},
|
||||||
.orientation =
|
.orientation =
|
||||||
{
|
{
|
||||||
Common::Vec<f32, 3>{1.0f, 0, 0},
|
Common::Vec3f{1.0f, 0, 0},
|
||||||
Common::Vec<f32, 3>{0, 1.0f, 0},
|
Common::Vec3f{0, 1.0f, 0},
|
||||||
Common::Vec<f32, 3>{0, 0, 1.0f},
|
Common::Vec3f{0, 0, 1.0f},
|
||||||
},
|
},
|
||||||
.attribute = {1},
|
.attribute = {1},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -88,8 +88,8 @@ void Mouse::UpdateStickInput() {
|
|||||||
last_mouse_change *= maximum_stick_range;
|
last_mouse_change *= maximum_stick_range;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetAxis(identifier, mouse_axis_x, last_mouse_change[0]);
|
SetAxis(identifier, mouse_axis_x, last_mouse_change.x);
|
||||||
SetAxis(identifier, mouse_axis_y, -last_mouse_change[1]);
|
SetAxis(identifier, mouse_axis_y, -last_mouse_change.y);
|
||||||
|
|
||||||
// Decay input over time
|
// Decay input over time
|
||||||
const float clamped_length = (std::min)(1.0f, length);
|
const float clamped_length = (std::min)(1.0f, length);
|
||||||
@@ -104,20 +104,20 @@ void Mouse::UpdateMotionInput() {
|
|||||||
const float sensitivity =
|
const float sensitivity =
|
||||||
IsMousePanningEnabled() ? default_motion_panning_sensitivity : default_motion_sensitivity;
|
IsMousePanningEnabled() ? default_motion_panning_sensitivity : default_motion_sensitivity;
|
||||||
|
|
||||||
const float rotation_velocity = std::sqrt(last_motion_change[0] * last_motion_change[0] +
|
const float rotation_velocity = std::sqrt(last_motion_change.x * last_motion_change.x +
|
||||||
last_motion_change[1] * last_motion_change[1]);
|
last_motion_change.y * last_motion_change.y);
|
||||||
|
|
||||||
// Clamp rotation speed
|
// Clamp rotation speed
|
||||||
if (rotation_velocity > maximum_rotation_speed / sensitivity) {
|
if (rotation_velocity > maximum_rotation_speed / sensitivity) {
|
||||||
const float multiplier = maximum_rotation_speed / rotation_velocity / sensitivity;
|
const float multiplier = maximum_rotation_speed / rotation_velocity / sensitivity;
|
||||||
last_motion_change[0] = last_motion_change[0] * multiplier;
|
last_motion_change.x = last_motion_change.x * multiplier;
|
||||||
last_motion_change[1] = last_motion_change[1] * multiplier;
|
last_motion_change.y = last_motion_change.y * multiplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
const BasicMotion motion_data{
|
const BasicMotion motion_data{
|
||||||
.gyro_x = last_motion_change[0] * sensitivity,
|
.gyro_x = last_motion_change.x * sensitivity,
|
||||||
.gyro_y = last_motion_change[1] * sensitivity,
|
.gyro_y = last_motion_change.y * sensitivity,
|
||||||
.gyro_z = last_motion_change[2] * sensitivity,
|
.gyro_z = last_motion_change.z * sensitivity,
|
||||||
.accel_x = 0,
|
.accel_x = 0,
|
||||||
.accel_y = 0,
|
.accel_y = 0,
|
||||||
.accel_z = 0,
|
.accel_z = 0,
|
||||||
@@ -125,46 +125,53 @@ void Mouse::UpdateMotionInput() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (IsMousePanningEnabled()) {
|
if (IsMousePanningEnabled()) {
|
||||||
last_motion_change[0] = 0;
|
last_motion_change.x = 0;
|
||||||
last_motion_change[1] = 0;
|
last_motion_change.y = 0;
|
||||||
}
|
}
|
||||||
last_motion_change[2] = 0;
|
last_motion_change.z = 0;
|
||||||
|
|
||||||
SetMotion(motion_identifier, 0, motion_data);
|
SetMotion(motion_identifier, 0, motion_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mouse::Move(int x, int y, int center_x, int center_y) {
|
void Mouse::Move(int x, int y, int center_x, int center_y) {
|
||||||
if (IsMousePanningEnabled()) {
|
if (IsMousePanningEnabled()) {
|
||||||
auto const mouse_change_int = Common::Vec<int, 2>(x, y) - Common::Vec<int, 2>(center_x, center_y);
|
const auto mouse_change =
|
||||||
auto const mouse_change = Common::Vec<float, 2>(float(mouse_change_int[0]), float(mouse_change_int[1]));
|
(Common::MakeVec(x, y) - Common::MakeVec(center_x, center_y)).Cast<float>();
|
||||||
auto const x_sensitivity = Settings::values.mouse_panning_x_sensitivity.GetValue() * default_panning_sensitivity;
|
const float x_sensitivity =
|
||||||
auto const y_sensitivity = Settings::values.mouse_panning_y_sensitivity.GetValue() * default_panning_sensitivity;
|
Settings::values.mouse_panning_x_sensitivity.GetValue() * default_panning_sensitivity;
|
||||||
auto const deadzone_cw = Settings::values.mouse_panning_deadzone_counterweight.GetValue() * default_deadzone_counterweight;
|
const float y_sensitivity =
|
||||||
last_motion_change += {-mouse_change[1] * x_sensitivity, -mouse_change[0] * y_sensitivity, 0};
|
Settings::values.mouse_panning_y_sensitivity.GetValue() * default_panning_sensitivity;
|
||||||
last_mouse_change[0] += mouse_change[0] * x_sensitivity;
|
const float deadzone_counterweight =
|
||||||
last_mouse_change[1] += mouse_change[1] * y_sensitivity;
|
Settings::values.mouse_panning_deadzone_counterweight.GetValue() *
|
||||||
// Bind the mouse change to [0 <= deadzone_cw <= 1.0]
|
default_deadzone_counterweight;
|
||||||
|
|
||||||
|
last_motion_change += {-mouse_change.y * x_sensitivity, -mouse_change.x * y_sensitivity, 0};
|
||||||
|
last_mouse_change.x += mouse_change.x * x_sensitivity;
|
||||||
|
last_mouse_change.y += mouse_change.y * y_sensitivity;
|
||||||
|
|
||||||
|
// Bind the mouse change to [0 <= deadzone_counterweight <= 1.0]
|
||||||
const float length = last_mouse_change.Length();
|
const float length = last_mouse_change.Length();
|
||||||
if (length < deadzone_cw && length != 0.0f) {
|
if (length < deadzone_counterweight && length != 0.0f) {
|
||||||
last_mouse_change /= length;
|
last_mouse_change /= length;
|
||||||
last_mouse_change *= deadzone_cw;
|
last_mouse_change *= deadzone_counterweight;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (button_pressed) {
|
if (button_pressed) {
|
||||||
const auto mouse_move = Common::Vec<int, 2>(x, y) - mouse_origin;
|
const auto mouse_move = Common::MakeVec<int>(x, y) - mouse_origin;
|
||||||
const float x_sensitivity =
|
const float x_sensitivity =
|
||||||
Settings::values.mouse_panning_x_sensitivity.GetValue() * default_stick_sensitivity;
|
Settings::values.mouse_panning_x_sensitivity.GetValue() * default_stick_sensitivity;
|
||||||
const float y_sensitivity =
|
const float y_sensitivity =
|
||||||
Settings::values.mouse_panning_y_sensitivity.GetValue() * default_stick_sensitivity;
|
Settings::values.mouse_panning_y_sensitivity.GetValue() * default_stick_sensitivity;
|
||||||
SetAxis(identifier, mouse_axis_x, float(mouse_move[0]) * x_sensitivity);
|
SetAxis(identifier, mouse_axis_x, static_cast<float>(mouse_move.x) * x_sensitivity);
|
||||||
SetAxis(identifier, mouse_axis_y, float(-mouse_move[1]) * y_sensitivity);
|
SetAxis(identifier, mouse_axis_y, static_cast<float>(-mouse_move.y) * y_sensitivity);
|
||||||
|
|
||||||
last_motion_change = {
|
last_motion_change = {
|
||||||
float(-mouse_move[1]) * x_sensitivity,
|
static_cast<float>(-mouse_move.y) * x_sensitivity,
|
||||||
float(-mouse_move[0]) * y_sensitivity,
|
static_cast<float>(-mouse_move.x) * y_sensitivity,
|
||||||
last_motion_change[2],
|
last_motion_change.z,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -213,18 +220,18 @@ void Mouse::ReleaseButton(MouseButton button) {
|
|||||||
SetAxis(identifier, mouse_axis_y, 0);
|
SetAxis(identifier, mouse_axis_y, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
last_motion_change[0] = 0;
|
last_motion_change.x = 0;
|
||||||
last_motion_change[1] = 0;
|
last_motion_change.y = 0;
|
||||||
|
|
||||||
button_pressed = false;
|
button_pressed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mouse::MouseWheelChange(int x, int y) {
|
void Mouse::MouseWheelChange(int x, int y) {
|
||||||
wheel_position[0] += x;
|
wheel_position.x += x;
|
||||||
wheel_position[1] += y;
|
wheel_position.y += y;
|
||||||
last_motion_change[2] += static_cast<f32>(y);
|
last_motion_change.z += static_cast<f32>(y);
|
||||||
SetAxis(identifier, wheel_axis_x, static_cast<f32>(wheel_position[0]));
|
SetAxis(identifier, wheel_axis_x, static_cast<f32>(wheel_position.x));
|
||||||
SetAxis(identifier, wheel_axis_y, static_cast<f32>(wheel_position[1]));
|
SetAxis(identifier, wheel_axis_y, static_cast<f32>(wheel_position.y));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mouse::ReleaseAllButtons() {
|
void Mouse::ReleaseAllButtons() {
|
||||||
|
|||||||
@@ -107,11 +107,11 @@ private:
|
|||||||
|
|
||||||
Common::Input::ButtonNames GetUIButtonName(const Common::ParamPackage& params) const;
|
Common::Input::ButtonNames GetUIButtonName(const Common::ParamPackage& params) const;
|
||||||
|
|
||||||
Common::Vec<int, 2> mouse_origin;
|
Common::Vec2<int> mouse_origin;
|
||||||
Common::Vec<int, 2> last_mouse_position;
|
Common::Vec2<int> last_mouse_position;
|
||||||
Common::Vec<float, 2> last_mouse_change;
|
Common::Vec2<float> last_mouse_change;
|
||||||
Common::Vec<float, 3> last_motion_change;
|
Common::Vec3<float> last_motion_change;
|
||||||
Common::Vec<int, 2> wheel_position;
|
Common::Vec2<int> wheel_position;
|
||||||
bool button_pressed = false;
|
bool button_pressed = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ add_library(video_core STATIC
|
|||||||
buffer_cache/buffer_cache.h
|
buffer_cache/buffer_cache.h
|
||||||
buffer_cache/memory_tracker_base.h
|
buffer_cache/memory_tracker_base.h
|
||||||
buffer_cache/usage_tracker.h
|
buffer_cache/usage_tracker.h
|
||||||
buffer_cache/virtual_range_cache.h
|
|
||||||
buffer_cache/word_manager.h
|
buffer_cache/word_manager.h
|
||||||
cache_types.h
|
cache_types.h
|
||||||
capture.h
|
capture.h
|
||||||
@@ -167,8 +166,6 @@ add_library(video_core STATIC
|
|||||||
renderer_vulkan/vk_fence_manager.h
|
renderer_vulkan/vk_fence_manager.h
|
||||||
renderer_vulkan/vk_graphics_pipeline.cpp
|
renderer_vulkan/vk_graphics_pipeline.cpp
|
||||||
renderer_vulkan/vk_graphics_pipeline.h
|
renderer_vulkan/vk_graphics_pipeline.h
|
||||||
renderer_vulkan/vk_multi_range_buffer.cpp
|
|
||||||
renderer_vulkan/vk_multi_range_buffer.h
|
|
||||||
renderer_vulkan/vk_master_semaphore.cpp
|
renderer_vulkan/vk_master_semaphore.cpp
|
||||||
renderer_vulkan/vk_master_semaphore.h
|
renderer_vulkan/vk_master_semaphore.h
|
||||||
renderer_vulkan/vk_pipeline_cache.cpp
|
renderer_vulkan/vk_pipeline_cache.cpp
|
||||||
|
|||||||
@@ -112,13 +112,6 @@ void BufferCache<P>::TickFrame() {
|
|||||||
async_buffers_death_ring.clear();
|
async_buffers_death_ring.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class P>
|
|
||||||
void BufferCache<P>::UnmapGPUMemory(size_t as_id, GPUVAddr gpu_addr, size_t size) {
|
|
||||||
if constexpr (requires { runtime.BindMultiRangeStorageBuffer(u64{}, bool{}); }) {
|
|
||||||
virtual_ranges.Unmap(as_id, gpu_addr, size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
void BufferCache<P>::WriteMemory(DAddr device_addr, u64 size) {
|
void BufferCache<P>::WriteMemory(DAddr device_addr, u64 size) {
|
||||||
if (memory_tracker.IsRegionGpuModified(device_addr, size)) {
|
if (memory_tracker.IsRegionGpuModified(device_addr, size)) {
|
||||||
@@ -215,8 +208,8 @@ bool BufferCache<P>::DMACopy(GPUVAddr src_address, GPUVAddr dest_address, u64 am
|
|||||||
BufferId buffer_b;
|
BufferId buffer_b;
|
||||||
do {
|
do {
|
||||||
channel_state->has_deleted_buffers = false;
|
channel_state->has_deleted_buffers = false;
|
||||||
buffer_a = FindBuffer(*cpu_src_address, static_cast<u32>(amount), false);
|
buffer_a = FindBuffer(*cpu_src_address, static_cast<u32>(amount));
|
||||||
buffer_b = FindBuffer(*cpu_dest_address, static_cast<u32>(amount), false);
|
buffer_b = FindBuffer(*cpu_dest_address, static_cast<u32>(amount));
|
||||||
} while (channel_state->has_deleted_buffers);
|
} while (channel_state->has_deleted_buffers);
|
||||||
auto& src_buffer = slot_buffers[buffer_a];
|
auto& src_buffer = slot_buffers[buffer_a];
|
||||||
auto& dest_buffer = slot_buffers[buffer_b];
|
auto& dest_buffer = slot_buffers[buffer_b];
|
||||||
@@ -272,7 +265,7 @@ bool BufferCache<P>::DMAClear(GPUVAddr dst_address, u64 amount, u32 value) {
|
|||||||
ClearDownload(*cpu_dst_address, size);
|
ClearDownload(*cpu_dst_address, size);
|
||||||
gpu_modified_ranges.Subtract(*cpu_dst_address, size);
|
gpu_modified_ranges.Subtract(*cpu_dst_address, size);
|
||||||
|
|
||||||
const BufferId buffer = FindBuffer(*cpu_dst_address, static_cast<u32>(size), false);
|
const BufferId buffer = FindBuffer(*cpu_dst_address, static_cast<u32>(size));
|
||||||
Buffer& dest_buffer = slot_buffers[buffer];
|
Buffer& dest_buffer = slot_buffers[buffer];
|
||||||
const u32 offset = dest_buffer.Offset(*cpu_dst_address);
|
const u32 offset = dest_buffer.Offset(*cpu_dst_address);
|
||||||
runtime.ClearBuffer(dest_buffer, offset, size, value);
|
runtime.ClearBuffer(dest_buffer, offset, size, value);
|
||||||
@@ -294,7 +287,7 @@ std::pair<typename P::Buffer*, u32> BufferCache<P>::ObtainBuffer(GPUVAddr gpu_ad
|
|||||||
template <class P>
|
template <class P>
|
||||||
std::pair<typename P::Buffer*, u32> BufferCache<P>::ObtainCPUBuffer(
|
std::pair<typename P::Buffer*, u32> BufferCache<P>::ObtainCPUBuffer(
|
||||||
DAddr device_addr, u32 size, ObtainBufferSynchronize sync_info, ObtainBufferOperation post_op) {
|
DAddr device_addr, u32 size, ObtainBufferSynchronize sync_info, ObtainBufferOperation post_op) {
|
||||||
const BufferId buffer_id = FindBuffer(device_addr, size, false);
|
const BufferId buffer_id = FindBuffer(device_addr, size);
|
||||||
Buffer& buffer = slot_buffers[buffer_id];
|
Buffer& buffer = slot_buffers[buffer_id];
|
||||||
|
|
||||||
// synchronize op
|
// synchronize op
|
||||||
@@ -1005,85 +998,11 @@ void BufferCache<P>::BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32
|
|||||||
channel_state->fast_bound_uniform_buffers[stage] &= ~(1u << binding_index);
|
channel_state->fast_bound_uniform_buffers[stage] &= ~(1u << binding_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class P>
|
|
||||||
void BufferCache<P>::ResolveMultiRangeStorage(Binding& binding, bool is_written,
|
|
||||||
std::vector<MultiRangeSegment>& pool) {
|
|
||||||
binding.segment_first = 0;
|
|
||||||
binding.segment_count = 0;
|
|
||||||
if constexpr (requires { runtime.BindMultiRangeStorageBuffer(u64{}, bool{}); }) {
|
|
||||||
if (binding.gpu_addr == 0 || binding.size == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (is_written && !runtime.PrefersSparseSources()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const VirtualSegments* found =
|
|
||||||
virtual_ranges.Query(*gpu_memory, binding.gpu_addr, binding.size);
|
|
||||||
if (!found || found->size() < 2) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const VirtualSegments segments = *found;
|
|
||||||
const u32 first = static_cast<u32>(pool.size());
|
|
||||||
const bool prefer_sparse = runtime.PrefersSparseSources();
|
|
||||||
for (const VirtualSegment& segment : segments) {
|
|
||||||
const BufferId buffer_id =
|
|
||||||
FindBuffer(segment.device_addr, segment.size, prefer_sparse);
|
|
||||||
if (!buffer_id) {
|
|
||||||
pool.resize(first);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
pool.push_back(MultiRangeSegment{
|
|
||||||
.buffer_id = buffer_id,
|
|
||||||
.device_addr = segment.device_addr,
|
|
||||||
.size = segment.size,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
binding.segment_first = first;
|
|
||||||
binding.segment_count = static_cast<u32>(segments.size());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class P>
|
|
||||||
bool BufferCache<P>::BindMultiRangeStorage(const Binding& binding, bool is_written,
|
|
||||||
std::span<const MultiRangeSegment> pool) {
|
|
||||||
if constexpr (requires { runtime.BindMultiRangeStorageBuffer(u64{}, bool{}); }) {
|
|
||||||
if (binding.segment_count < 2) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (binding.segment_first + binding.segment_count > pool.size()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const u64 key = (static_cast<u64>(gpu_memory->GetID()) << 48) ^ binding.gpu_addr;
|
|
||||||
runtime.ResetMultiRange();
|
|
||||||
for (u32 index = 0; index < binding.segment_count; ++index) {
|
|
||||||
const MultiRangeSegment& segment = pool[binding.segment_first + index];
|
|
||||||
Buffer& buffer = slot_buffers[segment.buffer_id];
|
|
||||||
TouchBuffer(buffer, segment.buffer_id);
|
|
||||||
if (SynchronizeBuffer(buffer, segment.device_addr, segment.size)) {
|
|
||||||
runtime.InvalidateMultiRange(key);
|
|
||||||
}
|
|
||||||
const u32 offset = buffer.Offset(segment.device_addr);
|
|
||||||
buffer.MarkUsage(offset, segment.size);
|
|
||||||
if (is_written) {
|
|
||||||
MarkWrittenBuffer(segment.buffer_id, segment.device_addr, segment.size);
|
|
||||||
}
|
|
||||||
runtime.PushMultiRangeSource(buffer, offset, segment.size);
|
|
||||||
}
|
|
||||||
return runtime.BindMultiRangeStorageBuffer(key, is_written);
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
void BufferCache<P>::BindHostGraphicsStorageBuffers(size_t stage) {
|
void BufferCache<P>::BindHostGraphicsStorageBuffers(size_t stage) {
|
||||||
u32 binding_index = 0;
|
u32 binding_index = 0;
|
||||||
ForEachEnabledBit(channel_state->enabled_storage_buffers[stage], [&](u32 index) {
|
ForEachEnabledBit(channel_state->enabled_storage_buffers[stage], [&](u32 index) {
|
||||||
const Binding& binding = channel_state->storage_buffers[stage][index];
|
const Binding& binding = channel_state->storage_buffers[stage][index];
|
||||||
const bool is_written = ((channel_state->written_storage_buffers[stage] >> index) & 1) != 0;
|
|
||||||
if (BindMultiRangeStorage(binding, is_written, graphics_segments)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Buffer& buffer = slot_buffers[binding.buffer_id];
|
Buffer& buffer = slot_buffers[binding.buffer_id];
|
||||||
TouchBuffer(buffer, binding.buffer_id);
|
TouchBuffer(buffer, binding.buffer_id);
|
||||||
const u32 size = binding.size;
|
const u32 size = binding.size;
|
||||||
@@ -1091,6 +1010,7 @@ void BufferCache<P>::BindHostGraphicsStorageBuffers(size_t stage) {
|
|||||||
|
|
||||||
const u32 offset = buffer.Offset(binding.device_addr);
|
const u32 offset = buffer.Offset(binding.device_addr);
|
||||||
buffer.MarkUsage(offset, size);
|
buffer.MarkUsage(offset, size);
|
||||||
|
const bool is_written = ((channel_state->written_storage_buffers[stage] >> index) & 1) != 0;
|
||||||
|
|
||||||
if (is_written) {
|
if (is_written) {
|
||||||
MarkWrittenBuffer(binding.buffer_id, binding.device_addr, size);
|
MarkWrittenBuffer(binding.buffer_id, binding.device_addr, size);
|
||||||
@@ -1219,11 +1139,6 @@ void BufferCache<P>::BindHostComputeStorageBuffers() {
|
|||||||
u32 binding_index = 0;
|
u32 binding_index = 0;
|
||||||
ForEachEnabledBit(channel_state->enabled_compute_storage_buffers, [&](u32 index) {
|
ForEachEnabledBit(channel_state->enabled_compute_storage_buffers, [&](u32 index) {
|
||||||
const Binding& binding = channel_state->compute_storage_buffers[index];
|
const Binding& binding = channel_state->compute_storage_buffers[index];
|
||||||
const bool is_written =
|
|
||||||
((channel_state->written_compute_storage_buffers >> index) & 1) != 0;
|
|
||||||
if (BindMultiRangeStorage(binding, is_written, compute_segments)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Buffer& buffer = slot_buffers[binding.buffer_id];
|
Buffer& buffer = slot_buffers[binding.buffer_id];
|
||||||
TouchBuffer(buffer, binding.buffer_id);
|
TouchBuffer(buffer, binding.buffer_id);
|
||||||
const u32 size = binding.size;
|
const u32 size = binding.size;
|
||||||
@@ -1231,6 +1146,8 @@ void BufferCache<P>::BindHostComputeStorageBuffers() {
|
|||||||
|
|
||||||
const u32 offset = buffer.Offset(binding.device_addr);
|
const u32 offset = buffer.Offset(binding.device_addr);
|
||||||
buffer.MarkUsage(offset, size);
|
buffer.MarkUsage(offset, size);
|
||||||
|
const bool is_written =
|
||||||
|
((channel_state->written_compute_storage_buffers >> index) & 1) != 0;
|
||||||
|
|
||||||
if (is_written) {
|
if (is_written) {
|
||||||
MarkWrittenBuffer(binding.buffer_id, binding.device_addr, size);
|
MarkWrittenBuffer(binding.buffer_id, binding.device_addr, size);
|
||||||
@@ -1276,7 +1193,6 @@ void BufferCache<P>::BindHostComputeTextureBuffers() {
|
|||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
void BufferCache<P>::DoUpdateGraphicsBuffers(bool is_indexed) {
|
void BufferCache<P>::DoUpdateGraphicsBuffers(bool is_indexed) {
|
||||||
graphics_segments.clear();
|
|
||||||
BufferOperations([&]() {
|
BufferOperations([&]() {
|
||||||
if (is_indexed) {
|
if (is_indexed) {
|
||||||
UpdateIndexBuffer();
|
UpdateIndexBuffer();
|
||||||
@@ -1296,7 +1212,6 @@ void BufferCache<P>::DoUpdateGraphicsBuffers(bool is_indexed) {
|
|||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
void BufferCache<P>::DoUpdateComputeBuffers() {
|
void BufferCache<P>::DoUpdateComputeBuffers() {
|
||||||
compute_segments.clear();
|
|
||||||
BufferOperations([&]() {
|
BufferOperations([&]() {
|
||||||
UpdateComputeUniformBuffers();
|
UpdateComputeUniformBuffers();
|
||||||
UpdateComputeStorageBuffers();
|
UpdateComputeStorageBuffers();
|
||||||
@@ -1319,11 +1234,11 @@ void BufferCache<P>::UpdateIndexBuffer() {
|
|||||||
auto inline_index_size = static_cast<u32>(draw_state.inline_index_draw_indexes.size());
|
auto inline_index_size = static_cast<u32>(draw_state.inline_index_draw_indexes.size());
|
||||||
u32 buffer_size = Common::AlignUp(inline_index_size, CACHING_PAGESIZE);
|
u32 buffer_size = Common::AlignUp(inline_index_size, CACHING_PAGESIZE);
|
||||||
if (inline_buffer_id == NULL_BUFFER_ID) [[unlikely]] {
|
if (inline_buffer_id == NULL_BUFFER_ID) [[unlikely]] {
|
||||||
inline_buffer_id = CreateBuffer(0, buffer_size, false);
|
inline_buffer_id = CreateBuffer(0, buffer_size);
|
||||||
}
|
}
|
||||||
if (slot_buffers[inline_buffer_id].SizeBytes() < buffer_size) [[unlikely]] {
|
if (slot_buffers[inline_buffer_id].SizeBytes() < buffer_size) [[unlikely]] {
|
||||||
slot_buffers.erase(inline_buffer_id);
|
slot_buffers.erase(inline_buffer_id);
|
||||||
inline_buffer_id = CreateBuffer(0, buffer_size, false);
|
inline_buffer_id = CreateBuffer(0, buffer_size);
|
||||||
}
|
}
|
||||||
channel_state->index_buffer = Binding{
|
channel_state->index_buffer = Binding{
|
||||||
.device_addr = 0,
|
.device_addr = 0,
|
||||||
@@ -1346,7 +1261,7 @@ void BufferCache<P>::UpdateIndexBuffer() {
|
|||||||
channel_state->index_buffer = Binding{
|
channel_state->index_buffer = Binding{
|
||||||
.device_addr = *device_addr,
|
.device_addr = *device_addr,
|
||||||
.size = size,
|
.size = size,
|
||||||
.buffer_id = FindBuffer(*device_addr, size, false),
|
.buffer_id = FindBuffer(*device_addr, size),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1383,7 +1298,7 @@ void BufferCache<P>::UpdateVertexBuffer(u32 index) {
|
|||||||
if (!gpu_memory->IsWithinGPUAddressRange(gpu_addr_end) || size >= 64_MiB) {
|
if (!gpu_memory->IsWithinGPUAddressRange(gpu_addr_end) || size >= 64_MiB) {
|
||||||
size = static_cast<u32>(gpu_memory->MaxContinuousRange(gpu_addr_begin, size));
|
size = static_cast<u32>(gpu_memory->MaxContinuousRange(gpu_addr_begin, size));
|
||||||
}
|
}
|
||||||
const BufferId buffer_id = FindBuffer(*device_addr, size, false);
|
const BufferId buffer_id = FindBuffer(*device_addr, size);
|
||||||
const Binding binding{
|
const Binding binding{
|
||||||
.device_addr = *device_addr,
|
.device_addr = *device_addr,
|
||||||
.size = size,
|
.size = size,
|
||||||
@@ -1404,7 +1319,7 @@ void BufferCache<P>::UpdateDrawIndirect() {
|
|||||||
binding = Binding{
|
binding = Binding{
|
||||||
.device_addr = *device_addr,
|
.device_addr = *device_addr,
|
||||||
.size = static_cast<u32>(size),
|
.size = static_cast<u32>(size),
|
||||||
.buffer_id = FindBuffer(*device_addr, static_cast<u32>(size), false),
|
.buffer_id = FindBuffer(*device_addr, static_cast<u32>(size)),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
if (current_draw_indirect->include_count) {
|
if (current_draw_indirect->include_count) {
|
||||||
@@ -1428,7 +1343,7 @@ void BufferCache<P>::UpdateUniformBuffers(size_t stage) {
|
|||||||
channel_state->dirty_uniform_buffers[stage] |= 1U << index;
|
channel_state->dirty_uniform_buffers[stage] |= 1U << index;
|
||||||
}
|
}
|
||||||
// Resolve buffer
|
// Resolve buffer
|
||||||
binding.buffer_id = FindBuffer(binding.device_addr, binding.size, false);
|
binding.buffer_id = FindBuffer(binding.device_addr, binding.size);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1437,10 +1352,8 @@ void BufferCache<P>::UpdateStorageBuffers(size_t stage) {
|
|||||||
ForEachEnabledBit(channel_state->enabled_storage_buffers[stage], [&](u32 index) {
|
ForEachEnabledBit(channel_state->enabled_storage_buffers[stage], [&](u32 index) {
|
||||||
// Resolve buffer
|
// Resolve buffer
|
||||||
Binding& binding = channel_state->storage_buffers[stage][index];
|
Binding& binding = channel_state->storage_buffers[stage][index];
|
||||||
const BufferId buffer_id = FindBuffer(binding.device_addr, binding.size, false);
|
const BufferId buffer_id = FindBuffer(binding.device_addr, binding.size);
|
||||||
binding.buffer_id = buffer_id;
|
binding.buffer_id = buffer_id;
|
||||||
const bool is_written = ((channel_state->written_storage_buffers[stage] >> index) & 1) != 0;
|
|
||||||
ResolveMultiRangeStorage(binding, is_written, graphics_segments);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1448,7 +1361,7 @@ template <class P>
|
|||||||
void BufferCache<P>::UpdateTextureBuffers(size_t stage) {
|
void BufferCache<P>::UpdateTextureBuffers(size_t stage) {
|
||||||
ForEachEnabledBit(channel_state->enabled_texture_buffers[stage], [&](u32 index) {
|
ForEachEnabledBit(channel_state->enabled_texture_buffers[stage], [&](u32 index) {
|
||||||
Binding& binding = channel_state->texture_buffers[stage][index];
|
Binding& binding = channel_state->texture_buffers[stage][index];
|
||||||
binding.buffer_id = FindBuffer(binding.device_addr, binding.size, false);
|
binding.buffer_id = FindBuffer(binding.device_addr, binding.size);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1472,7 +1385,7 @@ void BufferCache<P>::UpdateTransformFeedbackBuffer(u32 index) {
|
|||||||
channel_state->transform_feedback_buffers[index] = NULL_BINDING;
|
channel_state->transform_feedback_buffers[index] = NULL_BINDING;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const BufferId buffer_id = FindBuffer(*device_addr, size, false);
|
const BufferId buffer_id = FindBuffer(*device_addr, size);
|
||||||
channel_state->transform_feedback_buffers[index] = Binding{
|
channel_state->transform_feedback_buffers[index] = Binding{
|
||||||
.device_addr = *device_addr,
|
.device_addr = *device_addr,
|
||||||
.size = size,
|
.size = size,
|
||||||
@@ -1494,7 +1407,7 @@ void BufferCache<P>::UpdateComputeUniformBuffers() {
|
|||||||
binding.size = cbuf.size;
|
binding.size = cbuf.size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
binding.buffer_id = FindBuffer(binding.device_addr, binding.size, false);
|
binding.buffer_id = FindBuffer(binding.device_addr, binding.size);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1503,10 +1416,7 @@ void BufferCache<P>::UpdateComputeStorageBuffers() {
|
|||||||
ForEachEnabledBit(channel_state->enabled_compute_storage_buffers, [&](u32 index) {
|
ForEachEnabledBit(channel_state->enabled_compute_storage_buffers, [&](u32 index) {
|
||||||
// Resolve buffer
|
// Resolve buffer
|
||||||
Binding& binding = channel_state->compute_storage_buffers[index];
|
Binding& binding = channel_state->compute_storage_buffers[index];
|
||||||
binding.buffer_id = FindBuffer(binding.device_addr, binding.size, false);
|
binding.buffer_id = FindBuffer(binding.device_addr, binding.size);
|
||||||
const bool is_written =
|
|
||||||
((channel_state->written_compute_storage_buffers >> index) & 1) != 0;
|
|
||||||
ResolveMultiRangeStorage(binding, is_written, compute_segments);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1514,7 +1424,7 @@ template <class P>
|
|||||||
void BufferCache<P>::UpdateComputeTextureBuffers() {
|
void BufferCache<P>::UpdateComputeTextureBuffers() {
|
||||||
ForEachEnabledBit(channel_state->enabled_compute_texture_buffers, [&](u32 index) {
|
ForEachEnabledBit(channel_state->enabled_compute_texture_buffers, [&](u32 index) {
|
||||||
Binding& binding = channel_state->compute_texture_buffers[index];
|
Binding& binding = channel_state->compute_texture_buffers[index];
|
||||||
binding.buffer_id = FindBuffer(binding.device_addr, binding.size, false);
|
binding.buffer_id = FindBuffer(binding.device_addr, binding.size);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1530,7 +1440,7 @@ void BufferCache<P>::MarkWrittenBuffer(BufferId buffer_id, DAddr device_addr, u3
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
BufferId BufferCache<P>::FindBuffer(DAddr device_addr, u32 size, bool sparse_compatible) {
|
BufferId BufferCache<P>::FindBuffer(DAddr device_addr, u32 size) {
|
||||||
if (device_addr == 0) {
|
if (device_addr == 0) {
|
||||||
return NULL_BUFFER_ID;
|
return NULL_BUFFER_ID;
|
||||||
}
|
}
|
||||||
@@ -1540,18 +1450,10 @@ BufferId BufferCache<P>::FindBuffer(DAddr device_addr, u32 size, bool sparse_com
|
|||||||
Buffer& buffer = slot_buffers[buffer_id];
|
Buffer& buffer = slot_buffers[buffer_id];
|
||||||
WaitForGpuFenceIfNeeded(buffer);
|
WaitForGpuFenceIfNeeded(buffer);
|
||||||
if (buffer.IsInBounds(device_addr, size)) {
|
if (buffer.IsInBounds(device_addr, size)) {
|
||||||
bool usable = true;
|
return buffer_id;
|
||||||
if constexpr (requires { buffer.IsSparseCompatible(); }) {
|
|
||||||
if (sparse_compatible && !buffer.IsSparseCompatible()) {
|
|
||||||
usable = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (usable) {
|
|
||||||
return buffer_id;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return CreateBuffer(device_addr, size, sparse_compatible);
|
return CreateBuffer(device_addr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
@@ -1673,15 +1575,13 @@ void BufferCache<P>::JoinOverlap(BufferId new_buffer_id, BufferId overlap_id,
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
BufferId BufferCache<P>::CreateBuffer(DAddr device_addr, u32 wanted_size,
|
BufferId BufferCache<P>::CreateBuffer(DAddr device_addr, u32 wanted_size) {
|
||||||
bool sparse_compatible) {
|
|
||||||
DAddr device_addr_end = Common::AlignUp(device_addr + wanted_size, CACHING_PAGESIZE);
|
DAddr device_addr_end = Common::AlignUp(device_addr + wanted_size, CACHING_PAGESIZE);
|
||||||
device_addr = Common::AlignDown(device_addr, CACHING_PAGESIZE);
|
device_addr = Common::AlignDown(device_addr, CACHING_PAGESIZE);
|
||||||
wanted_size = static_cast<u32>(device_addr_end - device_addr);
|
wanted_size = static_cast<u32>(device_addr_end - device_addr);
|
||||||
const OverlapResult overlap = ResolveOverlaps(device_addr, wanted_size);
|
const OverlapResult overlap = ResolveOverlaps(device_addr, wanted_size);
|
||||||
const u32 size = static_cast<u32>(overlap.end - overlap.begin);
|
const u32 size = static_cast<u32>(overlap.end - overlap.begin);
|
||||||
const BufferId new_buffer_id =
|
const BufferId new_buffer_id = slot_buffers.insert(runtime, overlap.begin, size);
|
||||||
slot_buffers.insert(runtime, overlap.begin, size, sparse_compatible);
|
|
||||||
auto& new_buffer = slot_buffers[new_buffer_id];
|
auto& new_buffer = slot_buffers[new_buffer_id];
|
||||||
const size_t size_bytes = new_buffer.SizeBytes();
|
const size_t size_bytes = new_buffer.SizeBytes();
|
||||||
runtime.ClearBuffer(new_buffer, 0, size_bytes, 0);
|
runtime.ClearBuffer(new_buffer, 0, size_bytes, 0);
|
||||||
@@ -1845,7 +1745,7 @@ void BufferCache<P>::InlineMemoryImplementation(DAddr dest_address, size_t copy_
|
|||||||
ClearDownload(dest_address, copy_size);
|
ClearDownload(dest_address, copy_size);
|
||||||
gpu_modified_ranges.Subtract(dest_address, copy_size);
|
gpu_modified_ranges.Subtract(dest_address, copy_size);
|
||||||
|
|
||||||
BufferId buffer_id = FindBuffer(dest_address, static_cast<u32>(copy_size), false);
|
BufferId buffer_id = FindBuffer(dest_address, static_cast<u32>(copy_size));
|
||||||
auto& buffer = slot_buffers[buffer_id];
|
auto& buffer = slot_buffers[buffer_id];
|
||||||
SynchronizeBuffer(buffer, dest_address, static_cast<u32>(copy_size));
|
SynchronizeBuffer(buffer, dest_address, static_cast<u32>(copy_size));
|
||||||
|
|
||||||
@@ -1931,9 +1831,6 @@ void BufferCache<P>::DownloadBufferMemory(Buffer& buffer, DAddr device_addr, u64
|
|||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
void BufferCache<P>::DeleteBuffer(BufferId buffer_id, bool do_not_mark) {
|
void BufferCache<P>::DeleteBuffer(BufferId buffer_id, bool do_not_mark) {
|
||||||
if constexpr (requires { runtime.OnBufferDeleted(slot_buffers[buffer_id]); }) {
|
|
||||||
runtime.OnBufferDeleted(slot_buffers[buffer_id]);
|
|
||||||
}
|
|
||||||
bool dirty_index{false};
|
bool dirty_index{false};
|
||||||
boost::container::small_vector<u64, NUM_VERTEX_BUFFERS> dirty_vertex_buffers;
|
boost::container::small_vector<u64, NUM_VERTEX_BUFFERS> dirty_vertex_buffers;
|
||||||
const auto scalar_replace = [buffer_id](Binding& binding) {
|
const auto scalar_replace = [buffer_id](Binding& binding) {
|
||||||
@@ -2037,14 +1934,9 @@ Binding BufferCache<P>::StorageBufferBinding(GPUVAddr ssbo_addr, u32 cbuf_index,
|
|||||||
// The end address used for size calculation does not need to be aligned
|
// The end address used for size calculation does not need to be aligned
|
||||||
const DAddr cpu_end = Common::AlignUp(*device_addr + size, Core::DEVICE_PAGESIZE);
|
const DAddr cpu_end = Common::AlignUp(*device_addr + size, Core::DEVICE_PAGESIZE);
|
||||||
|
|
||||||
u32 binding_size = static_cast<u32>(cpu_end - *aligned_device_addr);
|
|
||||||
if (is_written) {
|
|
||||||
binding_size = aligned_size;
|
|
||||||
}
|
|
||||||
const Binding binding{
|
const Binding binding{
|
||||||
.device_addr = *aligned_device_addr,
|
.device_addr = *aligned_device_addr,
|
||||||
.gpu_addr = aligned_gpu_addr,
|
.size = is_written ? aligned_size : static_cast<u32>(cpu_end - *aligned_device_addr),
|
||||||
.size = binding_size,
|
|
||||||
.buffer_id = BufferId{},
|
.buffer_id = BufferId{},
|
||||||
};
|
};
|
||||||
return binding;
|
return binding;
|
||||||
|
|||||||
@@ -29,7 +29,6 @@
|
|||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
#include "common/slot_vector.h"
|
#include "common/slot_vector.h"
|
||||||
#include "video_core/buffer_cache/buffer_base.h"
|
#include "video_core/buffer_cache/buffer_base.h"
|
||||||
#include "video_core/buffer_cache/virtual_range_cache.h"
|
|
||||||
#include "video_core/control/channel_state_cache.h"
|
#include "video_core/control/channel_state_cache.h"
|
||||||
#include "video_core/delayed_destruction_ring.h"
|
#include "video_core/delayed_destruction_ring.h"
|
||||||
#include "video_core/dirty_flags.h"
|
#include "video_core/dirty_flags.h"
|
||||||
@@ -82,17 +81,8 @@ static constexpr u32 DEFAULT_SKIP_CACHE_SIZE = static_cast<u32>(4_KiB);
|
|||||||
|
|
||||||
struct Binding {
|
struct Binding {
|
||||||
DAddr device_addr{};
|
DAddr device_addr{};
|
||||||
GPUVAddr gpu_addr{};
|
|
||||||
u32 size{};
|
u32 size{};
|
||||||
BufferId buffer_id;
|
BufferId buffer_id;
|
||||||
u32 segment_first{};
|
|
||||||
u32 segment_count{};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MultiRangeSegment {
|
|
||||||
BufferId buffer_id;
|
|
||||||
DAddr device_addr{};
|
|
||||||
u32 size{};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TextureBufferBinding : Binding {
|
struct TextureBufferBinding : Binding {
|
||||||
@@ -225,14 +215,6 @@ public:
|
|||||||
|
|
||||||
void TickFrame();
|
void TickFrame();
|
||||||
|
|
||||||
bool BindMultiRangeStorage(const Binding& binding, bool is_written,
|
|
||||||
std::span<const MultiRangeSegment> pool);
|
|
||||||
|
|
||||||
void ResolveMultiRangeStorage(Binding& binding, bool is_written,
|
|
||||||
std::vector<MultiRangeSegment>& pool);
|
|
||||||
|
|
||||||
void UnmapGPUMemory(size_t as_id, GPUVAddr gpu_addr, size_t size);
|
|
||||||
|
|
||||||
void WriteMemory(DAddr device_addr, u64 size);
|
void WriteMemory(DAddr device_addr, u64 size);
|
||||||
|
|
||||||
void CachedWriteMemory(DAddr device_addr, u64 size);
|
void CachedWriteMemory(DAddr device_addr, u64 size);
|
||||||
@@ -432,7 +414,7 @@ private:
|
|||||||
|
|
||||||
void MarkWrittenBuffer(BufferId buffer_id, DAddr device_addr, u32 size);
|
void MarkWrittenBuffer(BufferId buffer_id, DAddr device_addr, u32 size);
|
||||||
|
|
||||||
[[nodiscard]] BufferId FindBuffer(DAddr device_addr, u32 size, bool sparse_compatible);
|
[[nodiscard]] BufferId FindBuffer(DAddr device_addr, u32 size);
|
||||||
|
|
||||||
void WaitForGpuFenceIfNeeded(Buffer& buffer);
|
void WaitForGpuFenceIfNeeded(Buffer& buffer);
|
||||||
|
|
||||||
@@ -440,8 +422,7 @@ private:
|
|||||||
|
|
||||||
void JoinOverlap(BufferId new_buffer_id, BufferId overlap_id, bool accumulate_stream_score);
|
void JoinOverlap(BufferId new_buffer_id, BufferId overlap_id, bool accumulate_stream_score);
|
||||||
|
|
||||||
[[nodiscard]] BufferId CreateBuffer(DAddr device_addr, u32 wanted_size,
|
[[nodiscard]] BufferId CreateBuffer(DAddr device_addr, u32 wanted_size);
|
||||||
bool sparse_compatible);
|
|
||||||
|
|
||||||
void Register(BufferId buffer_id);
|
void Register(BufferId buffer_id);
|
||||||
|
|
||||||
@@ -532,9 +513,6 @@ private:
|
|||||||
using TickType = u64;
|
using TickType = u64;
|
||||||
};
|
};
|
||||||
Common::LeastRecentlyUsedCache<LRUItemParams> lru_cache;
|
Common::LeastRecentlyUsedCache<LRUItemParams> lru_cache;
|
||||||
VirtualRangeCache virtual_ranges;
|
|
||||||
std::vector<MultiRangeSegment> graphics_segments;
|
|
||||||
std::vector<MultiRangeSegment> compute_segments;
|
|
||||||
u64 frame_tick = 0;
|
u64 frame_tick = 0;
|
||||||
u64 total_used_memory = 0;
|
u64 total_used_memory = 0;
|
||||||
u64 minimum_memory = 0;
|
u64 minimum_memory = 0;
|
||||||
|
|||||||
@@ -1,173 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <atomic>
|
|
||||||
#include <limits>
|
|
||||||
#include <mutex>
|
|
||||||
#include <optional>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include <boost/container/small_vector.hpp>
|
|
||||||
|
|
||||||
#include "common/common_types.h"
|
|
||||||
#include "common/container/unordered_map.h"
|
|
||||||
#include "video_core/memory_manager.h"
|
|
||||||
|
|
||||||
namespace VideoCommon {
|
|
||||||
|
|
||||||
struct VirtualSegment {
|
|
||||||
GPUVAddr gpu_addr;
|
|
||||||
DAddr device_addr;
|
|
||||||
u32 size;
|
|
||||||
};
|
|
||||||
|
|
||||||
using VirtualSegments = boost::container::small_vector<VirtualSegment, 8>;
|
|
||||||
|
|
||||||
class VirtualRangeCache {
|
|
||||||
public:
|
|
||||||
static constexpr size_t MAX_ENTRIES = 8192;
|
|
||||||
static constexpr size_t MAX_DEFERRED = 4096;
|
|
||||||
|
|
||||||
const VirtualSegments* Query(Tegra::MemoryManager& memory, GPUVAddr gpu_addr, u32 size) {
|
|
||||||
if (has_deferred.load(std::memory_order_acquire)) {
|
|
||||||
ApplyDeferred();
|
|
||||||
}
|
|
||||||
if (entries.size() > MAX_ENTRIES) {
|
|
||||||
entries.clear();
|
|
||||||
}
|
|
||||||
const size_t as_id = memory.GetID();
|
|
||||||
const u64 key = MakeKey(as_id, gpu_addr);
|
|
||||||
const auto it = entries.find(key);
|
|
||||||
if (it != entries.end() && it->second.as_id == as_id &&
|
|
||||||
it->second.gpu_addr == gpu_addr && it->second.size == size) {
|
|
||||||
return &it->second.segments;
|
|
||||||
}
|
|
||||||
Entry entry{};
|
|
||||||
entry.as_id = as_id;
|
|
||||||
entry.gpu_addr = gpu_addr;
|
|
||||||
entry.size = size;
|
|
||||||
const auto ranges = memory.GetSubmappedRange(gpu_addr, size);
|
|
||||||
GPUVAddr expected = gpu_addr;
|
|
||||||
bool contiguous = true;
|
|
||||||
for (const auto& [range_addr, range_size] : ranges) {
|
|
||||||
if (range_addr != expected || range_size == 0) {
|
|
||||||
contiguous = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
const std::optional<DAddr> device_addr = memory.GpuToCpuAddress(range_addr);
|
|
||||||
if (!device_addr || *device_addr == 0) {
|
|
||||||
contiguous = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (range_size > static_cast<size_t>((std::numeric_limits<u32>::max)())) {
|
|
||||||
contiguous = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
entry.segments.push_back(VirtualSegment{
|
|
||||||
.gpu_addr = range_addr,
|
|
||||||
.device_addr = *device_addr,
|
|
||||||
.size = static_cast<u32>(range_size),
|
|
||||||
});
|
|
||||||
expected += range_size;
|
|
||||||
}
|
|
||||||
if (!contiguous || expected != gpu_addr + size) {
|
|
||||||
entry.segments.clear();
|
|
||||||
}
|
|
||||||
const auto result = entries.insert_or_assign(key, std::move(entry));
|
|
||||||
return &result.first->second.segments;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Unmap(size_t as_id, GPUVAddr gpu_addr, u64 size) {
|
|
||||||
if (size == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
std::scoped_lock lock{deferred_mutex};
|
|
||||||
if (!deferred.empty()) {
|
|
||||||
DeferredUnmap& last = deferred.back();
|
|
||||||
if (last.as_id == as_id && last.gpu_addr + last.size == gpu_addr) {
|
|
||||||
last.size += size;
|
|
||||||
has_deferred.store(true, std::memory_order_release);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (deferred.size() >= MAX_DEFERRED) {
|
|
||||||
deferred.clear();
|
|
||||||
deferred_overflow = true;
|
|
||||||
} else {
|
|
||||||
deferred.push_back(DeferredUnmap{
|
|
||||||
.as_id = as_id,
|
|
||||||
.gpu_addr = gpu_addr,
|
|
||||||
.size = size,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
has_deferred.store(true, std::memory_order_release);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct Entry {
|
|
||||||
VirtualSegments segments;
|
|
||||||
size_t as_id{};
|
|
||||||
GPUVAddr gpu_addr{};
|
|
||||||
u32 size{};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct DeferredUnmap {
|
|
||||||
size_t as_id;
|
|
||||||
GPUVAddr gpu_addr;
|
|
||||||
u64 size;
|
|
||||||
};
|
|
||||||
|
|
||||||
static u64 MakeKey(size_t as_id, GPUVAddr gpu_addr) {
|
|
||||||
return (static_cast<u64>(as_id) << 48) ^ gpu_addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ApplyDeferred() {
|
|
||||||
std::vector<DeferredUnmap> pending;
|
|
||||||
bool overflow = false;
|
|
||||||
{
|
|
||||||
std::scoped_lock lock{deferred_mutex};
|
|
||||||
has_deferred.store(false, std::memory_order_release);
|
|
||||||
pending.swap(deferred);
|
|
||||||
overflow = deferred_overflow;
|
|
||||||
deferred_overflow = false;
|
|
||||||
}
|
|
||||||
if (overflow) {
|
|
||||||
entries.clear();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (pending.empty() || entries.empty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (auto it = entries.begin(); it != entries.end();) {
|
|
||||||
const Entry& entry = it->second;
|
|
||||||
const GPUVAddr entry_end = entry.gpu_addr + entry.size;
|
|
||||||
bool overlaps = false;
|
|
||||||
for (const DeferredUnmap& unmap : pending) {
|
|
||||||
if (unmap.as_id != entry.as_id) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (entry.gpu_addr < unmap.gpu_addr + unmap.size && unmap.gpu_addr < entry_end) {
|
|
||||||
overlaps = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (overlaps) {
|
|
||||||
it = entries.erase(it);
|
|
||||||
} else {
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
::Common::unordered_map<u64, Entry> entries;
|
|
||||||
std::vector<DeferredUnmap> deferred;
|
|
||||||
std::mutex deferred_mutex;
|
|
||||||
std::atomic<bool> has_deferred{false};
|
|
||||||
bool deferred_overflow{};
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace VideoCommon
|
|
||||||
@@ -55,11 +55,11 @@ constexpr u64 GpuClockMultiplier(Settings::GpuClock clock) {
|
|||||||
|
|
||||||
struct GPU::Impl {
|
struct GPU::Impl {
|
||||||
explicit Impl(Core::System& system_, bool is_async_, bool use_nvdec_)
|
explicit Impl(Core::System& system_, bool is_async_, bool use_nvdec_)
|
||||||
: gpu_thread{system_}
|
: system{system_}
|
||||||
, system{system_}
|
|
||||||
, use_nvdec{use_nvdec_}
|
, use_nvdec{use_nvdec_}
|
||||||
, shader_notify()
|
, shader_notify()
|
||||||
, is_async{is_async_}
|
, is_async{is_async_}
|
||||||
|
, gpu_thread{system_}
|
||||||
{}
|
{}
|
||||||
|
|
||||||
~Impl() = default;
|
~Impl() = default;
|
||||||
@@ -301,10 +301,6 @@ struct GPU::Impl {
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destruction of thread must be done before all (non trivial)
|
|
||||||
// previous members has been destroyed
|
|
||||||
VideoCommon::GPUThread::ThreadManager gpu_thread;
|
|
||||||
|
|
||||||
Core::System& system;
|
Core::System& system;
|
||||||
|
|
||||||
std::unique_ptr<VideoCore::RendererBase> renderer;
|
std::unique_ptr<VideoCore::RendererBase> renderer;
|
||||||
@@ -333,6 +329,7 @@ struct GPU::Impl {
|
|||||||
|
|
||||||
const bool is_async;
|
const bool is_async;
|
||||||
|
|
||||||
|
VideoCommon::GPUThread::ThreadManager gpu_thread;
|
||||||
std::unique_ptr<Core::Frontend::GraphicsContext> cpu_context;
|
std::unique_ptr<Core::Frontend::GraphicsContext> cpu_context;
|
||||||
|
|
||||||
Tegra::Control::Scheduler scheduler;
|
Tegra::Control::Scheduler scheduler;
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ constexpr std::array PROGRAM_LUT{
|
|||||||
Buffer::Buffer(BufferCacheRuntime&, VideoCommon::NullBufferParams null_params)
|
Buffer::Buffer(BufferCacheRuntime&, VideoCommon::NullBufferParams null_params)
|
||||||
: VideoCommon::BufferBase(null_params) {}
|
: VideoCommon::BufferBase(null_params) {}
|
||||||
|
|
||||||
Buffer::Buffer(BufferCacheRuntime& runtime, DAddr cpu_addr_, u64 size_bytes_, bool)
|
Buffer::Buffer(BufferCacheRuntime& runtime, DAddr cpu_addr_, u64 size_bytes_)
|
||||||
: VideoCommon::BufferBase(cpu_addr_, size_bytes_) {
|
: VideoCommon::BufferBase(cpu_addr_, size_bytes_) {
|
||||||
buffer.Create();
|
buffer.Create();
|
||||||
if (runtime.device.HasDebuggingToolAttached()) {
|
if (runtime.device.HasDebuggingToolAttached()) {
|
||||||
|
|||||||
@@ -23,8 +23,7 @@ class BufferCacheRuntime;
|
|||||||
|
|
||||||
class Buffer : public VideoCommon::BufferBase {
|
class Buffer : public VideoCommon::BufferBase {
|
||||||
public:
|
public:
|
||||||
explicit Buffer(BufferCacheRuntime&, DAddr cpu_addr, u64 size_bytes,
|
explicit Buffer(BufferCacheRuntime&, DAddr cpu_addr, u64 size_bytes);
|
||||||
bool sparse_compatible);
|
|
||||||
explicit Buffer(BufferCacheRuntime&, VideoCommon::NullBufferParams);
|
explicit Buffer(BufferCacheRuntime&, VideoCommon::NullBufferParams);
|
||||||
|
|
||||||
void ImmediateUpload(size_t offset, std::span<const u8> data) noexcept;
|
void ImmediateUpload(size_t offset, std::span<const u8> data) noexcept;
|
||||||
|
|||||||
@@ -56,8 +56,7 @@ size_t BytesPerIndex(VkIndexType index_type) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vk::Buffer CreateBuffer(const Device& device, const MemoryAllocator& memory_allocator, u64 size,
|
vk::Buffer CreateBuffer(const Device& device, const MemoryAllocator& memory_allocator, u64 size) {
|
||||||
VkDeviceSize sparse_alignment) {
|
|
||||||
VkBufferUsageFlags flags =
|
VkBufferUsageFlags flags =
|
||||||
VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT |
|
VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT |
|
||||||
VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT |
|
VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT |
|
||||||
@@ -83,9 +82,6 @@ vk::Buffer CreateBuffer(const Device& device, const MemoryAllocator& memory_allo
|
|||||||
.queueFamilyIndexCount = 0,
|
.queueFamilyIndexCount = 0,
|
||||||
.pQueueFamilyIndices = nullptr,
|
.pQueueFamilyIndices = nullptr,
|
||||||
};
|
};
|
||||||
if (sparse_alignment > 1) {
|
|
||||||
return memory_allocator.CreateBuffer(buffer_ci, MemoryUsage::DeviceLocal, sparse_alignment);
|
|
||||||
}
|
|
||||||
return memory_allocator.CreateBuffer(buffer_ci, MemoryUsage::DeviceLocal);
|
return memory_allocator.CreateBuffer(buffer_ci, MemoryUsage::DeviceLocal);
|
||||||
}
|
}
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
@@ -103,14 +99,10 @@ Buffer::Buffer(BufferCacheRuntime& runtime, VideoCommon::NullBufferParams null_p
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Buffer::Buffer(BufferCacheRuntime& runtime, DAddr cpu_addr_, u64 size_bytes_,
|
Buffer::Buffer(BufferCacheRuntime& runtime, DAddr cpu_addr_, u64 size_bytes_)
|
||||||
bool sparse_compatible_)
|
|
||||||
: VideoCommon::BufferBase(cpu_addr_, size_bytes_), device{&runtime.device},
|
: VideoCommon::BufferBase(cpu_addr_, size_bytes_), device{&runtime.device},
|
||||||
scheduler{&runtime.scheduler},
|
scheduler{&runtime.scheduler},
|
||||||
buffer{CreateBuffer(*device, runtime.memory_allocator, SizeBytes(),
|
buffer{CreateBuffer(*device, runtime.memory_allocator, SizeBytes())}, tracker{SizeBytes()} {
|
||||||
runtime.SparseAlignmentFor(sparse_compatible_))},
|
|
||||||
tracker{SizeBytes()} {
|
|
||||||
sparse_compatible = sparse_compatible_;
|
|
||||||
if (runtime.device.HasDebuggingToolAttached()) {
|
if (runtime.device.HasDebuggingToolAttached()) {
|
||||||
buffer.SetObjectNameEXT(fmt::format("Buffer {:#x}", CpuAddr()).c_str());
|
buffer.SetObjectNameEXT(fmt::format("Buffer {:#x}", CpuAddr()).c_str());
|
||||||
}
|
}
|
||||||
@@ -356,8 +348,7 @@ BufferCacheRuntime::BufferCacheRuntime(const Device& device_, MemoryAllocator& m
|
|||||||
: device{device_}, memory_allocator{memory_allocator_}, scheduler{scheduler_},
|
: device{device_}, memory_allocator{memory_allocator_}, scheduler{scheduler_},
|
||||||
staging_pool{staging_pool_}, guest_descriptor_queue{guest_descriptor_queue_},
|
staging_pool{staging_pool_}, guest_descriptor_queue{guest_descriptor_queue_},
|
||||||
quad_index_pass(device, scheduler, descriptor_pool, staging_pool,
|
quad_index_pass(device, scheduler, descriptor_pool, staging_pool,
|
||||||
compute_pass_descriptor_queue),
|
compute_pass_descriptor_queue) {
|
||||||
multi_range_buffers(device_) {
|
|
||||||
const VkDriverIdKHR driver_id = device.GetDriverID();
|
const VkDriverIdKHR driver_id = device.GetDriverID();
|
||||||
limit_dynamic_storage_buffers = driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY ||
|
limit_dynamic_storage_buffers = driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY ||
|
||||||
driver_id == VK_DRIVER_ID_ARM_PROPRIETARY;
|
driver_id == VK_DRIVER_ID_ARM_PROPRIETARY;
|
||||||
@@ -545,37 +536,6 @@ void BufferCacheRuntime::ClearBuffer(VkBuffer dest_buffer, u32 offset, size_t si
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BufferCacheRuntime::BindMultiRangeStorageBuffer(u64 key, bool is_written) {
|
|
||||||
if (multi_range_sources.empty() || multi_range_total == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const MultiRangeRef ref = multi_range_buffers.Get(device, scheduler, memory_allocator, key,
|
|
||||||
multi_range_sources, multi_range_total);
|
|
||||||
if (ref.handle == VK_NULL_HANDLE) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (is_written && !ref.sparse) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (ref.needs_gather) {
|
|
||||||
PreCopyBarrier();
|
|
||||||
VkDeviceSize dst_offset = 0;
|
|
||||||
for (const MultiRangeSource& source : multi_range_sources) {
|
|
||||||
const std::array<VideoCommon::BufferCopy, 1> copy{VideoCommon::BufferCopy{
|
|
||||||
.src_offset = u64(source.offset),
|
|
||||||
.dst_offset = u64(dst_offset),
|
|
||||||
.size = size_t(source.size),
|
|
||||||
}};
|
|
||||||
CopyBuffer(ref.handle, source.handle, copy, false);
|
|
||||||
dst_offset += source.size;
|
|
||||||
}
|
|
||||||
PostCopyBarrier();
|
|
||||||
multi_range_buffers.MarkGathered(key);
|
|
||||||
}
|
|
||||||
guest_descriptor_queue.AddBuffer(ref.handle, ref.address, 0, ref.size);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BufferCacheRuntime::BindIndexBuffer(PrimitiveTopology topology, IndexFormat index_format,
|
void BufferCacheRuntime::BindIndexBuffer(PrimitiveTopology topology, IndexFormat index_format,
|
||||||
u32 base_vertex, u32 num_indices, VkBuffer buffer,
|
u32 base_vertex, u32 num_indices, VkBuffer buffer,
|
||||||
u32 offset, [[maybe_unused]] u32 size) {
|
u32 offset, [[maybe_unused]] u32 size) {
|
||||||
|
|||||||
@@ -8,14 +8,11 @@
|
|||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
#include <boost/container/small_vector.hpp>
|
|
||||||
|
|
||||||
#include "video_core/buffer_cache/buffer_cache_base.h"
|
#include "video_core/buffer_cache/buffer_cache_base.h"
|
||||||
#include "video_core/buffer_cache/memory_tracker_base.h"
|
#include "video_core/buffer_cache/memory_tracker_base.h"
|
||||||
#include "video_core/buffer_cache/usage_tracker.h"
|
#include "video_core/buffer_cache/usage_tracker.h"
|
||||||
#include "video_core/engines/maxwell_3d.h"
|
#include "video_core/engines/maxwell_3d.h"
|
||||||
#include "video_core/renderer_vulkan/vk_compute_pass.h"
|
#include "video_core/renderer_vulkan/vk_compute_pass.h"
|
||||||
#include "video_core/renderer_vulkan/vk_multi_range_buffer.h"
|
|
||||||
#include "video_core/renderer_vulkan/vk_staging_buffer_pool.h"
|
#include "video_core/renderer_vulkan/vk_staging_buffer_pool.h"
|
||||||
#include "video_core/renderer_vulkan/vk_update_descriptor.h"
|
#include "video_core/renderer_vulkan/vk_update_descriptor.h"
|
||||||
#include "video_core/surface.h"
|
#include "video_core/surface.h"
|
||||||
@@ -34,8 +31,7 @@ class BufferCacheRuntime;
|
|||||||
class Buffer : public VideoCommon::BufferBase {
|
class Buffer : public VideoCommon::BufferBase {
|
||||||
public:
|
public:
|
||||||
explicit Buffer(BufferCacheRuntime&, VideoCommon::NullBufferParams null_params);
|
explicit Buffer(BufferCacheRuntime&, VideoCommon::NullBufferParams null_params);
|
||||||
explicit Buffer(BufferCacheRuntime& runtime, VAddr cpu_addr_, u64 size_bytes_,
|
explicit Buffer(BufferCacheRuntime& runtime, VAddr cpu_addr_, u64 size_bytes_);
|
||||||
bool sparse_compatible_);
|
|
||||||
|
|
||||||
[[nodiscard]] VkBufferView View(u32 offset, u32 size, VideoCore::Surface::PixelFormat format);
|
[[nodiscard]] VkBufferView View(u32 offset, u32 size, VideoCore::Surface::PixelFormat format);
|
||||||
|
|
||||||
@@ -47,14 +43,6 @@ public:
|
|||||||
return device_address;
|
return device_address;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] bool IsSparseCompatible() const noexcept {
|
|
||||||
return sparse_compatible;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] vk::MemoryLocation Location() const noexcept {
|
|
||||||
return buffer.Location();
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool IsRegionUsed(u64 offset, u64 size) const noexcept {
|
[[nodiscard]] bool IsRegionUsed(u64 offset, u64 size) const noexcept {
|
||||||
return tracker.IsUsed(offset, size);
|
return tracker.IsUsed(offset, size);
|
||||||
}
|
}
|
||||||
@@ -89,7 +77,6 @@ private:
|
|||||||
VkDeviceAddress device_address{};
|
VkDeviceAddress device_address{};
|
||||||
u64 last_usage_tick{};
|
u64 last_usage_tick{};
|
||||||
bool is_null{};
|
bool is_null{};
|
||||||
bool sparse_compatible{};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class QuadArrayIndexBuffer;
|
class QuadArrayIndexBuffer;
|
||||||
@@ -138,7 +125,7 @@ public:
|
|||||||
|
|
||||||
void PreCopyBarrier();
|
void PreCopyBarrier();
|
||||||
|
|
||||||
void CopyBuffer(VkBuffer dst_buffer, VkBuffer src_buffer,
|
void CopyBuffer(VkBuffer src_buffer, VkBuffer dst_buffer,
|
||||||
std::span<const VideoCommon::BufferCopy> copies, bool barrier,
|
std::span<const VideoCommon::BufferCopy> copies, bool barrier,
|
||||||
bool can_reorder_upload = false);
|
bool can_reorder_upload = false);
|
||||||
|
|
||||||
@@ -168,46 +155,6 @@ public:
|
|||||||
return ref.mapped_span;
|
return ref.mapped_span;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] VkDeviceSize SparseAlignmentFor(bool sparse_compatible) const noexcept {
|
|
||||||
if (!sparse_compatible || !multi_range_buffers.use_sparse) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return multi_range_buffers.block_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool PrefersSparseSources() const noexcept {
|
|
||||||
return multi_range_buffers.use_sparse;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ResetMultiRange() noexcept {
|
|
||||||
multi_range_sources.clear();
|
|
||||||
multi_range_total = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PushMultiRangeSource(const Buffer& buffer, u32 offset, u32 size) {
|
|
||||||
const vk::MemoryLocation location = buffer.Location();
|
|
||||||
multi_range_sources.push_back(MultiRangeSource{
|
|
||||||
.handle = buffer.Handle(),
|
|
||||||
.memory = location.memory,
|
|
||||||
.memory_offset = location.offset,
|
|
||||||
.offset = offset,
|
|
||||||
.size = size,
|
|
||||||
.write_tick = buffer.getWriteTick(),
|
|
||||||
.memory_type = location.memory_type,
|
|
||||||
});
|
|
||||||
multi_range_total += size;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BindMultiRangeStorageBuffer(u64 key, bool is_written);
|
|
||||||
|
|
||||||
void InvalidateMultiRange(u64 key) {
|
|
||||||
multi_range_buffers.Invalidate(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnBufferDeleted(const Buffer& buffer) {
|
|
||||||
multi_range_buffers.DropOwner(scheduler, buffer.Handle());
|
|
||||||
}
|
|
||||||
|
|
||||||
void BindUniformBuffer(const Buffer& buffer, u32 offset, u32 size) {
|
void BindUniformBuffer(const Buffer& buffer, u32 offset, u32 size) {
|
||||||
BindBuffer(buffer, offset, size);
|
BindBuffer(buffer, offset, size);
|
||||||
}
|
}
|
||||||
@@ -261,10 +208,6 @@ private:
|
|||||||
std::unique_ptr<Uint8Pass> uint8_pass;
|
std::unique_ptr<Uint8Pass> uint8_pass;
|
||||||
QuadIndexedPass quad_index_pass;
|
QuadIndexedPass quad_index_pass;
|
||||||
|
|
||||||
MultiRangeBufferCache multi_range_buffers;
|
|
||||||
boost::container::small_vector<MultiRangeSource, 16> multi_range_sources;
|
|
||||||
VkDeviceSize multi_range_total{};
|
|
||||||
|
|
||||||
bool limit_dynamic_storage_buffers = false;
|
bool limit_dynamic_storage_buffers = false;
|
||||||
u32 max_dynamic_storage_buffers = (std::numeric_limits<u32>::max)();
|
u32 max_dynamic_storage_buffers = (std::numeric_limits<u32>::max)();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,338 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <mutex>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
#include "video_core/renderer_vulkan/vk_multi_range_buffer.h"
|
|
||||||
#include "video_core/renderer_vulkan/vk_scheduler.h"
|
|
||||||
#include "video_core/vulkan_common/vulkan_device.h"
|
|
||||||
|
|
||||||
namespace Vulkan {
|
|
||||||
|
|
||||||
MultiRangeBufferCache::MultiRangeBufferCache(const Device& device) {
|
|
||||||
sparse_usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT |
|
|
||||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
|
|
||||||
if (device.IsBufferDeviceAddressSupported()) {
|
|
||||||
sparse_usage |= VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
|
|
||||||
}
|
|
||||||
if (!device.IsSparseBindingSupported()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
u32 memory_type_bits = 0;
|
|
||||||
const VkDeviceSize queried = QueryBlockSize(device, memory_type_bits);
|
|
||||||
if (queried == 0 || memory_type_bits == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
block_size = queried;
|
|
||||||
sparse_memory_type_bits = memory_type_bits;
|
|
||||||
use_sparse = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
VkDeviceSize MultiRangeBufferCache::QueryBlockSize(const Device& device,
|
|
||||||
u32& memory_type_bits) const {
|
|
||||||
const VkDevice logical = *device.GetLogical();
|
|
||||||
const auto& dld = device.GetDispatchLoader();
|
|
||||||
const VkBufferCreateInfo probe_ci{
|
|
||||||
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.flags = VK_BUFFER_CREATE_SPARSE_BINDING_BIT | VK_BUFFER_CREATE_SPARSE_ALIASED_BIT,
|
|
||||||
.size = DEFAULT_BLOCK_SIZE,
|
|
||||||
.usage = sparse_usage,
|
|
||||||
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
|
||||||
.queueFamilyIndexCount = 0,
|
|
||||||
.pQueueFamilyIndices = nullptr,
|
|
||||||
};
|
|
||||||
VkBuffer probe{};
|
|
||||||
if (dld.vkCreateBuffer(logical, &probe_ci, nullptr, &probe) != VK_SUCCESS) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
const SparseBuffer owned{probe, logical, dld};
|
|
||||||
const VkBufferMemoryRequirementsInfo2 reqs_info{
|
|
||||||
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.buffer = probe,
|
|
||||||
};
|
|
||||||
VkMemoryRequirements2 reqs2{
|
|
||||||
.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.memoryRequirements = {},
|
|
||||||
};
|
|
||||||
dld.vkGetBufferMemoryRequirements2(logical, &reqs_info, &reqs2);
|
|
||||||
memory_type_bits = reqs2.memoryRequirements.memoryTypeBits;
|
|
||||||
return reqs2.memoryRequirements.alignment;
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 MultiRangeBufferCache::HashSources(std::span<const MultiRangeSource> sources) const {
|
|
||||||
u64 hash = 0xcbf29ce484222325ULL;
|
|
||||||
const auto mix = [&hash](u64 value) {
|
|
||||||
hash ^= value;
|
|
||||||
hash *= 0x100000001b3ULL;
|
|
||||||
};
|
|
||||||
for (const MultiRangeSource& source : sources) {
|
|
||||||
mix(u64(source.handle));
|
|
||||||
mix(u64(source.offset));
|
|
||||||
mix(u64(source.size));
|
|
||||||
}
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 MultiRangeBufferCache::HashContent(std::span<const MultiRangeSource> sources) const {
|
|
||||||
u64 hash = 0xcbf29ce484222325ULL;
|
|
||||||
for (const MultiRangeSource& source : sources) {
|
|
||||||
hash ^= source.write_tick;
|
|
||||||
hash *= 0x100000001b3ULL;
|
|
||||||
}
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MultiRangeBufferCache::CanBindSparse(std::span<const MultiRangeSource> sources) const {
|
|
||||||
return use_sparse &&
|
|
||||||
std::none_of(sources.begin(), sources.end(),
|
|
||||||
[block = block_size, bits = sparse_memory_type_bits](auto const& e) {
|
|
||||||
const VkDeviceSize memory_offset = e.memory_offset + e.offset;
|
|
||||||
return e.memory == VK_NULL_HANDLE || e.memory_type >= 32 ||
|
|
||||||
((bits >> e.memory_type) & 1) == 0 ||
|
|
||||||
(memory_offset % block) != 0 || (e.size % block) != 0;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
SparseBuffer MultiRangeBufferCache::CreateSparse(const Device& device, Scheduler& scheduler,
|
|
||||||
std::span<const MultiRangeSource> sources,
|
|
||||||
VkDeviceSize total) {
|
|
||||||
const VkDevice logical = *device.GetLogical();
|
|
||||||
const auto& dld = device.GetDispatchLoader();
|
|
||||||
const VkBufferCreateInfo buffer_ci{
|
|
||||||
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.flags = VK_BUFFER_CREATE_SPARSE_BINDING_BIT | VK_BUFFER_CREATE_SPARSE_ALIASED_BIT,
|
|
||||||
.size = total,
|
|
||||||
.usage = sparse_usage,
|
|
||||||
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
|
||||||
.queueFamilyIndexCount = 0,
|
|
||||||
.pQueueFamilyIndices = nullptr,
|
|
||||||
};
|
|
||||||
VkBuffer raw{};
|
|
||||||
if (dld.vkCreateBuffer(logical, &buffer_ci, nullptr, &raw) != VK_SUCCESS) {
|
|
||||||
return SparseBuffer{};
|
|
||||||
}
|
|
||||||
SparseBuffer handle{raw, logical, dld};
|
|
||||||
std::vector<VkSparseMemoryBind> binds;
|
|
||||||
binds.reserve(sources.size());
|
|
||||||
VkDeviceSize resource_offset = 0;
|
|
||||||
for (const MultiRangeSource& source : sources) {
|
|
||||||
binds.push_back(VkSparseMemoryBind{
|
|
||||||
.resourceOffset = resource_offset,
|
|
||||||
.size = source.size,
|
|
||||||
.memory = source.memory,
|
|
||||||
.memoryOffset = source.memory_offset + source.offset,
|
|
||||||
.flags = 0,
|
|
||||||
});
|
|
||||||
resource_offset += source.size;
|
|
||||||
}
|
|
||||||
const VkSparseBufferMemoryBindInfo buffer_bind{
|
|
||||||
.buffer = raw,
|
|
||||||
.bindCount = static_cast<u32>(binds.size()),
|
|
||||||
.pBinds = binds.data(),
|
|
||||||
};
|
|
||||||
const VkBindSparseInfo bind_info{
|
|
||||||
.sType = VK_STRUCTURE_TYPE_BIND_SPARSE_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.waitSemaphoreCount = 0,
|
|
||||||
.pWaitSemaphores = nullptr,
|
|
||||||
.bufferBindCount = 1,
|
|
||||||
.pBufferBinds = &buffer_bind,
|
|
||||||
.imageOpaqueBindCount = 0,
|
|
||||||
.pImageOpaqueBinds = nullptr,
|
|
||||||
.imageBindCount = 0,
|
|
||||||
.pImageBinds = nullptr,
|
|
||||||
.signalSemaphoreCount = 0,
|
|
||||||
.pSignalSemaphores = nullptr,
|
|
||||||
};
|
|
||||||
const VkFenceCreateInfo fence_ci{
|
|
||||||
.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.flags = 0,
|
|
||||||
};
|
|
||||||
vk::Fence fence = device.GetLogical().CreateFence(fence_ci);
|
|
||||||
VkResult bind_result = VK_ERROR_UNKNOWN;
|
|
||||||
{
|
|
||||||
std::scoped_lock lock{scheduler.submit_mutex};
|
|
||||||
bind_result = device.GetGraphicsQueue().BindSparse(bind_info, *fence);
|
|
||||||
}
|
|
||||||
if (bind_result != VK_SUCCESS) {
|
|
||||||
return SparseBuffer{};
|
|
||||||
}
|
|
||||||
fence.Wait();
|
|
||||||
return handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MultiRangeBufferCache::RetireEntry(Scheduler& scheduler, Entry& entry) {
|
|
||||||
if (!entry.sparse_handle && !entry.gathered) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (retired.size() == retired.capacity()) {
|
|
||||||
DrainRetired(scheduler);
|
|
||||||
}
|
|
||||||
if (retired.size() == retired.capacity()) {
|
|
||||||
u64 oldest = retired.front().tick;
|
|
||||||
for (const Retired& item : retired) {
|
|
||||||
if (item.tick < oldest) {
|
|
||||||
oldest = item.tick;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
scheduler.Wait(oldest);
|
|
||||||
DrainRetired(scheduler);
|
|
||||||
}
|
|
||||||
retired.push_back(Retired{
|
|
||||||
.handle = std::move(entry.sparse_handle),
|
|
||||||
.gathered = std::move(entry.gathered),
|
|
||||||
.tick = scheduler.CurrentTick(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void MultiRangeBufferCache::DrainRetired(Scheduler& scheduler) {
|
|
||||||
size_t index = 0;
|
|
||||||
while (index < retired.size()) {
|
|
||||||
if (scheduler.IsFree(retired[index].tick)) {
|
|
||||||
if (index + 1 != retired.size()) {
|
|
||||||
retired[index] = std::move(retired.back());
|
|
||||||
}
|
|
||||||
retired.pop_back();
|
|
||||||
} else {
|
|
||||||
++index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MultiRangeRef MultiRangeBufferCache::Get(const Device& device, Scheduler& scheduler,
|
|
||||||
MemoryAllocator& memory_allocator, u64 key,
|
|
||||||
std::span<const MultiRangeSource> sources,
|
|
||||||
VkDeviceSize total) {
|
|
||||||
if (sources.empty() || total == 0) {
|
|
||||||
return MultiRangeRef{};
|
|
||||||
}
|
|
||||||
if (!retired.empty()) {
|
|
||||||
DrainRetired(scheduler);
|
|
||||||
}
|
|
||||||
const u64 geometry = HashSources(sources);
|
|
||||||
const u64 content = HashContent(sources);
|
|
||||||
const auto it = entries.find(key);
|
|
||||||
if (it != entries.end() && it->second.geometry == geometry && it->second.size == total) {
|
|
||||||
Entry& entry = it->second;
|
|
||||||
if (entry.content != content) {
|
|
||||||
entry.content = content;
|
|
||||||
entry.dirty = true;
|
|
||||||
}
|
|
||||||
MultiRangeRef ref{
|
|
||||||
.handle = *entry.sparse_handle,
|
|
||||||
.address = entry.address,
|
|
||||||
.size = entry.size,
|
|
||||||
.sparse = true,
|
|
||||||
.needs_gather = false,
|
|
||||||
};
|
|
||||||
if (!entry.sparse_handle) {
|
|
||||||
ref.handle = *entry.gathered;
|
|
||||||
ref.sparse = false;
|
|
||||||
ref.needs_gather = entry.dirty;
|
|
||||||
}
|
|
||||||
return ref;
|
|
||||||
}
|
|
||||||
if (it != entries.end()) {
|
|
||||||
RetireEntry(scheduler, it->second);
|
|
||||||
entries.erase(it);
|
|
||||||
}
|
|
||||||
|
|
||||||
Entry entry{};
|
|
||||||
entry.geometry = geometry;
|
|
||||||
entry.content = content;
|
|
||||||
entry.size = total;
|
|
||||||
if (CanBindSparse(sources)) {
|
|
||||||
entry.sparse_handle = CreateSparse(device, scheduler, sources, total);
|
|
||||||
if (entry.sparse_handle) {
|
|
||||||
entry.owners.reserve(sources.size());
|
|
||||||
for (const MultiRangeSource& source : sources) {
|
|
||||||
entry.owners.push_back(source.handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!entry.sparse_handle) {
|
|
||||||
VkBufferUsageFlags flags = VK_BUFFER_USAGE_TRANSFER_SRC_BIT |
|
|
||||||
VK_BUFFER_USAGE_TRANSFER_DST_BIT |
|
|
||||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
|
|
||||||
if (device.IsBufferDeviceAddressSupported()) {
|
|
||||||
flags |= VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
|
|
||||||
}
|
|
||||||
const VkBufferCreateInfo gather_ci{
|
|
||||||
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.flags = 0,
|
|
||||||
.size = total,
|
|
||||||
.usage = flags,
|
|
||||||
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
|
||||||
.queueFamilyIndexCount = 0,
|
|
||||||
.pQueueFamilyIndices = nullptr,
|
|
||||||
};
|
|
||||||
entry.gathered = memory_allocator.CreateBuffer(gather_ci, MemoryUsage::DeviceLocal);
|
|
||||||
entry.dirty = true;
|
|
||||||
}
|
|
||||||
if (device.IsBufferDeviceAddressSupported()) {
|
|
||||||
VkBuffer address_handle = *entry.sparse_handle;
|
|
||||||
if (!entry.sparse_handle) {
|
|
||||||
address_handle = *entry.gathered;
|
|
||||||
}
|
|
||||||
entry.address = device.GetLogical().GetBufferDeviceAddress(address_handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
MultiRangeRef ref{
|
|
||||||
.handle = *entry.sparse_handle,
|
|
||||||
.address = entry.address,
|
|
||||||
.size = entry.size,
|
|
||||||
.sparse = true,
|
|
||||||
.needs_gather = false,
|
|
||||||
};
|
|
||||||
if (!entry.sparse_handle) {
|
|
||||||
ref.handle = *entry.gathered;
|
|
||||||
ref.sparse = false;
|
|
||||||
ref.needs_gather = true;
|
|
||||||
}
|
|
||||||
entries.emplace(key, std::move(entry));
|
|
||||||
return ref;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MultiRangeBufferCache::MarkGathered(u64 key) {
|
|
||||||
if (auto const it = entries.find(key); it != entries.end()) {
|
|
||||||
it->second.dirty = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MultiRangeBufferCache::DropOwner(Scheduler& scheduler, VkBuffer owner) {
|
|
||||||
if (owner == VK_NULL_HANDLE) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (auto it = entries.begin(); it != entries.end();) {
|
|
||||||
Entry& entry = it->second;
|
|
||||||
bool owned = false;
|
|
||||||
for (const VkBuffer handle : entry.owners) {
|
|
||||||
if (handle == owner) {
|
|
||||||
owned = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!owned) {
|
|
||||||
++it;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
RetireEntry(scheduler, entry);
|
|
||||||
it = entries.erase(it);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MultiRangeBufferCache::Invalidate(u64 key) {
|
|
||||||
if (auto const it = entries.find(key); it != entries.end()) {
|
|
||||||
it->second.dirty = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Vulkan
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user