mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-10-20 08:46:33 -04:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1557422f15 | |||
| 989768aa46 |
Vendored
+283
-293
File diff suppressed because it is too large
Load Diff
Vendored
+278
-288
File diff suppressed because it is too large
Load Diff
Vendored
+278
-288
File diff suppressed because it is too large
Load Diff
Vendored
+278
-288
File diff suppressed because it is too large
Load Diff
Vendored
+278
-288
File diff suppressed because it is too large
Load Diff
Vendored
+278
-288
File diff suppressed because it is too large
Load Diff
Vendored
+278
-288
File diff suppressed because it is too large
Load Diff
Vendored
+278
-288
File diff suppressed because it is too large
Load Diff
Vendored
+278
-288
File diff suppressed because it is too large
Load Diff
Vendored
+278
-288
File diff suppressed because it is too large
Load Diff
Vendored
+278
-288
File diff suppressed because it is too large
Load Diff
Vendored
+278
-288
File diff suppressed because it is too large
Load Diff
Vendored
+278
-288
File diff suppressed because it is too large
Load Diff
Vendored
+335
-340
File diff suppressed because it is too large
Load Diff
Vendored
+278
-288
File diff suppressed because it is too large
Load Diff
Vendored
+278
-288
File diff suppressed because it is too large
Load Diff
Vendored
+278
-288
File diff suppressed because it is too large
Load Diff
Vendored
+278
-288
File diff suppressed because it is too large
Load Diff
Vendored
+278
-288
File diff suppressed because it is too large
Load Diff
Vendored
+278
-288
File diff suppressed because it is too large
Load Diff
Vendored
+278
-288
File diff suppressed because it is too large
Load Diff
Vendored
+278
-288
File diff suppressed because it is too large
Load Diff
Vendored
+278
-288
File diff suppressed because it is too large
Load Diff
Vendored
+278
-288
File diff suppressed because it is too large
Load Diff
Vendored
+278
-288
File diff suppressed because it is too large
Load Diff
Vendored
+278
-288
File diff suppressed because it is too large
Load Diff
Vendored
+278
-288
File diff suppressed because it is too large
Load Diff
@@ -696,7 +696,7 @@
|
||||
<string name="control_stick">عصا التحكم</string>
|
||||
<string name="right_stick">العصا اليمنى</string>
|
||||
<string name="c_stick">عصا-C</string>
|
||||
<string name="pressed">مضغوط</string>
|
||||
<string name="pressed">ضغط العصا</string>
|
||||
<string name="range">النطاق</string>
|
||||
<string name="deadzone">المنطقة الميتة</string>
|
||||
<string name="modifier">معدل</string>
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
|
||||
<string name="input_overlay_options">虛擬按鍵設定</string>
|
||||
<string name="input_overlay_options_description">調整虛擬按鍵的位置與顯示設定</string>
|
||||
<string name="edit_overlay_layout">編輯虛擬按鍵</string>
|
||||
<string name="edit_overlay_layout">調整虛擬按鍵</string>
|
||||
<string name="edit_overlay_layout_description">調整虛擬按鍵的位置和大小</string>
|
||||
|
||||
|
||||
@@ -253,8 +253,8 @@
|
||||
<string name="install_firmware_warning">跳過安裝韌體?</string>
|
||||
<string name="emulator_data">設定模擬器資料</string>
|
||||
<string name="emulator_data_description">模擬器需要金鑰才能正常執行,同時建議安裝韌體以啟動 QLaunch 小程式</string>
|
||||
<string name="permissions">授予權限</string>
|
||||
<string name="permissions_description">授予權限以使用模擬器的特定功能</string>
|
||||
<string name="permissions">授予通知權限</string>
|
||||
<string name="permissions_description">授予 Eden 傳送通知的權限以使用模擬器的特定功能</string>
|
||||
<string name="install_firmware_warning_description">許多遊戲需要韌體才能正常運作</string>
|
||||
<string name="install_firmware_warning_help">https://yuzu-mirror.github.io/help/quickstart/#guide-introduction</string>
|
||||
<string name="notifications">通知</string>
|
||||
@@ -268,8 +268,8 @@
|
||||
<string name="device_manufacturer">製造商</string>
|
||||
<string name="device_model">型號</string>
|
||||
<string name="product">型號代碼</string>
|
||||
<string name="android_version">安卓版本</string>
|
||||
<string name="android_security_patch">安卓安全性修補程式等級</string>
|
||||
<string name="android_version">Android 版本</string>
|
||||
<string name="android_security_patch">Android 安全性修補程式等級</string>
|
||||
<string name="build_id">版本號碼</string>
|
||||
<string name="general_information">基本資訊</string>
|
||||
<string name="hardware">硬體</string>
|
||||
@@ -287,7 +287,7 @@
|
||||
<string name="warning_skip">跳過</string>
|
||||
<string name="warning_cancel">取消</string>
|
||||
<string name="install_amiibo_keys">安裝 Amiibo 金鑰</string>
|
||||
<string name="install_amiibo_keys_description">需要先安裝才能在遊戲中使用 Amiibo</string>
|
||||
<string name="install_amiibo_keys_description">安裝 Amiibo 以在日後遊玩時使用</string>
|
||||
<string name="gpu_driver_fetcher">GPU 驅動程式下載器</string>
|
||||
<string name="gpu_driver_manager">GPU 驅動程式管理員</string>
|
||||
<string name="install_gpu_driver_description">安裝替代驅動程式以取得潛在的更佳效能或準確度</string>
|
||||
@@ -417,17 +417,17 @@
|
||||
<string name="custom_driver_not_supported">您的裝置不支援自訂驅動程式</string>
|
||||
<string name="custom_driver_not_supported_description">此裝置不支援注入自訂驅動程式\n請以後再來查看是否已新增支援!</string>
|
||||
<string name="manage_yuzu_data">管理 Eden 資料</string>
|
||||
<string name="manage_yuzu_data_description">安裝韌體、金鑰,導入/導出使用者資料及安裝其它項目!</string>
|
||||
<string name="manage_yuzu_data_description">安裝韌體、金鑰,匯入/匯出使用者資料及安裝其它項目!</string>
|
||||
<string name="game_folders">遊戲資料夾</string>
|
||||
<string name="deep_scan">深度掃描</string>
|
||||
<string name="add_game_folder">新增遊戲資料夾</string>
|
||||
<string name="folder_already_added">這個資料夾已經新增過了!</string>
|
||||
<string name="game_folder_properties">遊戲資料夾設定</string>
|
||||
<plurals name="saves_import_failed">
|
||||
<item quantity="other">%d 個存檔導入失敗</item>
|
||||
<item quantity="other">%d 個存檔匯入失敗</item>
|
||||
</plurals>
|
||||
<plurals name="saves_import_success">
|
||||
<item quantity="other">成功導入 %d 個存檔</item>
|
||||
<item quantity="other">成功匯入 %d 個存檔</item>
|
||||
</plurals>
|
||||
<string name="no_save_data_found">找不到儲存資料</string>
|
||||
<string name="verify_installed_content">驗證已安裝內容的完整性</string>
|
||||
@@ -578,9 +578,9 @@
|
||||
<string name="skip_cpu_inner_invalidation">跳過 CPU 內部失效處理</string>
|
||||
<string name="skip_cpu_inner_invalidation_description">在記憶體更新期間跳過某些 CPU 端快取的失效處理,減少 CPU 使用率並提高其性能。可能會導致某些遊戲出現故障或當機</string>
|
||||
<string name="nce_invalidation_gpu_readback">在 NCE 無效化前進行 GPU 回讀</string>
|
||||
<string name="nce_invalidation_gpu_readback_description">(暫時性功能)修復 \"終結者瑪格諾莉亞:霧中綻放\" 及其它使用虛幻引擎之遊戲中的當機問題,可能會降低效能。此功能正在改善中</string>
|
||||
<string name="nce_invalidation_gpu_readback_description">(暫時性功能)修復《終結者瑪格諾莉亞:霧中綻放》及其它使用虛幻引擎之遊戲中的當機問題,可能會降低效能。此功能正在改善中</string>
|
||||
<string name="fix_bloom_effects">修正光暈特效</string>
|
||||
<string name="fix_bloom_effects_description">在 \"薩爾達傳說:織夢島\" 和 \"薩爾達傳說:智慧的再現\" 中減少光暈模糊的問題並移除 \"橫衝直撞:狂飆樂園重製版\" 中的光暈效果(適用於 Adreno A6XX - A7XX/ Turnip)。警告:可能會在其它遊戲中導致圖形異常</string>
|
||||
<string name="fix_bloom_effects_description">在《薩爾達傳說:織夢島》和《薩爾達傳說:智慧的再現》中減少光暈模糊的問題並移除《橫衝直撞:狂飆樂園重製版》中的光暈效果(適用於 Adreno A6XX - A7XX/ Turnip)。警告:可能會在其它遊戲中導致圖形異常</string>
|
||||
<string name="emulate_bgr565">模擬 BGR565</string>
|
||||
<string name="emulate_bgr565_description">修正遊戲中出現的色彩反轉、圖形異常或陰影異常</string>
|
||||
<string name="rescale_hack">啟用舊版重新縮放處理</string>
|
||||
@@ -603,7 +603,7 @@
|
||||
<string name="extensions">擴充功能</string>
|
||||
|
||||
<string name="dyna_state">擴展動態狀態</string>
|
||||
<string name="dyna_state_description">控制擴展動態狀態中可使用的功能數量,較高的數值可根據驅動程式支援的動態狀態減少管線編譯的次數</string>
|
||||
<string name="dyna_state_description">控制 Vulkan 擴展動態狀態中可使用的功能數量,較高的數值可根據驅動程式支援的動態狀態減少管線編譯的次數</string>
|
||||
<string name="disabled">停用</string>
|
||||
<string name="vertex_input_dynamic_state">頂點輸入動態狀態</string>
|
||||
<string name="vertex_input_dynamic_state_description">啟用此功能可提供更彈性的頂點輸入處理方式,並可能減少頂點/緩衝區的管線編譯時間</string>
|
||||
@@ -808,7 +808,7 @@
|
||||
<string name="recommended_driver">推薦驅動程式:</string>
|
||||
<string name="gpu_model">GPU 型號</string>
|
||||
<string name="unsupported_gpu">不支援的 GPU</string>
|
||||
<string name="unsupported_gpu_warning">您的 GPU 不支援驅動程式注入,不建議嘗試設定自訂驅動程式</string>
|
||||
<string name="unsupported_gpu_warning">您的 GPU 不支援驅動程式注入,不建議嘗試安裝自訂驅動程式</string>
|
||||
|
||||
<!-- Preferences Screen -->
|
||||
<string name="preferences_settings">設定</string>
|
||||
@@ -892,7 +892,7 @@
|
||||
<string name="select_content_type">內容類型</string>
|
||||
<string name="updates_and_dlc">更新及 DLC</string>
|
||||
<string name="mods_and_cheats">模組及金手指</string>
|
||||
<string name="addon_notice">重要的˙附加元件通知</string>
|
||||
<string name="addon_notice">注意!</string>
|
||||
<!-- \"cheats/" "romfs/" and \"exefs/ should not be translated -->
|
||||
<string name="addon_notice_description">若要安裝模組及金手指,您必須選擇一個包含 cheats/、romfs/ 或 exefs/ 的目錄。我們無法驗證這些內容是否與您的遊戲相容,所以請謹慎安裝!</string>
|
||||
<string name="invalid_directory">無效的目錄</string>
|
||||
@@ -981,7 +981,7 @@
|
||||
<string name="emulation_pause">暫停模擬</string>
|
||||
<string name="emulation_unpause">繼續模擬</string>
|
||||
<string name="emulation_input_overlay">疊加層/虛擬按鍵設定</string>
|
||||
<string name="load_amiibo">導入 Amiibo</string>
|
||||
<string name="load_amiibo">匯入 Amiibo</string>
|
||||
<string name="touchscreen">觸控螢幕</string>
|
||||
<string name="lock_drawer">鎖定側邊選單</string>
|
||||
<string name="unlock_drawer">解鎖側邊選單</string>
|
||||
@@ -1128,6 +1128,16 @@
|
||||
<string name="freedreno_clear_all">全部清除</string>
|
||||
<string name="freedreno_saved">Freedreno 設定已儲存</string>
|
||||
<string name="freedreno_cleared_all">已清除所有 Freedreno 變數</string>
|
||||
<string name="freedreno_variable_added">變數 %1$s 已新增</string>
|
||||
<string name="freedreno_preset_applied">設定檔 \"%1$s\" 已套用</string>
|
||||
<string name="freedreno_error_empty_name">變數名稱不可空白</string>
|
||||
<string name="freedreno_error_setting_variable">變數設定失敗</string>
|
||||
<string name="freedreno_info_title">關於 Freedreno 設定</string>
|
||||
<string name="freedreno_info_description">透過調整 Freedreno/Turnip GPU 驅動程式的設定來偵錯、分析和最佳化效能,會自動儲存變更。詳情請參閱 https://docs.mesa3d.org/drivers/freedreno.html</string>
|
||||
<string name="freedreno_per_game_title">Freedreno 設定</string>
|
||||
<string name="freedreno_per_game_description">調整此遊戲的 GPU 驅動程式設定</string>
|
||||
<string name="freedreno_per_game_saved">Freedreno 設定已儲存</string>
|
||||
|
||||
<!-- Gamepad Buttons -->
|
||||
<string name="gamepad_d_pad">方向鍵</string>
|
||||
<string name="gamepad_left_stick">左搖桿</string>
|
||||
@@ -1136,14 +1146,17 @@
|
||||
<string name="gamepad_screenshot">螢幕截圖</string>
|
||||
|
||||
<!-- Disk shader cache -->
|
||||
<string name="building_shaders">正在建置著色器</string>
|
||||
<string name="building_shaders">正在編譯著色器</string>
|
||||
|
||||
<!-- App options -->
|
||||
<string name="change_app_theme">變更應用程式主題</string>
|
||||
<string name="theme_default">預設</string>
|
||||
<string name="theme_material_you">質感設計3</string>
|
||||
<string name="app_settings">Eden介面設定</string>
|
||||
<string name="theme_material_you">Material You</string>
|
||||
<string name="app_settings">Eden 介面設定</string>
|
||||
<string name="theme_and_color">主題和顏色</string>
|
||||
<string name="fullscreen_mode">全螢幕模式</string>
|
||||
<string name="fullscreen_mode_description">在使用 Eden 時隱藏 Android 系統的導覽列,在直向時從螢幕底部往上滑以暫時顯示它們;橫向時則從螢幕側邊往內滑動</string>
|
||||
|
||||
<!-- Theme Modes -->
|
||||
<string name="change_theme_mode">變更主題模式</string>
|
||||
<string name="theme_mode_follow_system">跟隨系統</string>
|
||||
@@ -1152,18 +1165,26 @@
|
||||
|
||||
<!-- Black backgrounds theme -->
|
||||
<string name="use_black_backgrounds">黑色背景</string>
|
||||
<string name="use_black_backgrounds_description">使用深色主題時,套用黑色背景。</string>
|
||||
<string name="use_black_backgrounds_description">使用深色主題時套用黑色背景</string>
|
||||
|
||||
<!-- Buttons -->
|
||||
<string name="enable_folder_button">遊戲資料夾</string>
|
||||
<string name="enable_folder_button_description">在 Eden 首頁顯示新增遊戲資料夾的按鈕</string>
|
||||
<string name="enable_qlaunch_button">QLaunch</string>
|
||||
<string name="enable_qlaunch_button_description">在 Eden 首頁顯示 QLaunch 按鈕</string>
|
||||
|
||||
<!-- App Language -->
|
||||
<string name="app_language">語言</string>
|
||||
<string name="app_language_description">選擇Eden顯示的語言</string>
|
||||
<string name="app_language_description">選擇 Eden 顯示的語言</string>
|
||||
<string name="app_language_system">跟隨系統</string>
|
||||
<!-- Static Themes -->
|
||||
<string name="static_theme_color">主題色彩</string>
|
||||
<string name="eden_theme">Eden</string>
|
||||
<string name="violet">紫色</string>
|
||||
<string name="blue">藍色</string>
|
||||
<string name="cyan">青色</string>
|
||||
<string name="red">紅色</string>
|
||||
<string name="green">綠色</string>
|
||||
<string name="yellow">黃色</string>
|
||||
<string name="orange">橘色</string>
|
||||
<string name="pink">粉紅色</string>
|
||||
@@ -1185,14 +1206,28 @@
|
||||
<string name="applets_menu_description">更改小程式前端和設定</string>
|
||||
|
||||
<string name="applet_hle">自訂前端</string>
|
||||
<string name="applet_lle">Switch小程式</string>
|
||||
<string name="applet_lle">Switch 小程式</string>
|
||||
|
||||
<string name="swkbd_applet">軟體鍵盤</string>
|
||||
|
||||
<string name="airplane_mode">飛航模式</string>
|
||||
<string name="airplane_mode_description">將飛航模式傳遞給Switch作業系統</string>
|
||||
<string name="airplane_mode_description">將飛航模式傳遞給 Switch 作業系統</string>
|
||||
|
||||
<string name="enable_overlay">啟用小程式虛擬按鍵</string>
|
||||
<string name="enable_overlay_description">啟用 Horizon OS 內建的小程式虛擬按鍵,長按 Home 鍵 1 秒以顯示虛擬按鍵</string>
|
||||
|
||||
<!-- Profile Management -->
|
||||
<string name="profile_manager">使用者管理</string>
|
||||
<string name="profile_manager_description">更改使用者名稱、圖片及新增或刪除使用者</string>
|
||||
<string name="profile_add_user">新增使用者</string>
|
||||
<string name="profile_new_user">新增使用者</string>
|
||||
<string name="profile_edit_user">編輯使用者資料</string>
|
||||
<string name="profile_edit">編輯</string>
|
||||
<string name="profile_delete">刪除</string>
|
||||
<string name="profile_username">使用者名稱</string>
|
||||
<string name="profile_uuid">使用者 ID (通用唯一辨識碼)</string>
|
||||
<string name="profile_uuid_description">這是此使用者設定檔的唯一識別碼,建立後就無法進行更改</string>
|
||||
<!-- Licenses screen strings -->
|
||||
<string name="licenses">授權</string>
|
||||
<string name="license_fidelityfx_fsr_description">來自 AMD 的升級圖像品質</string>
|
||||
</resources>
|
||||
</resources>
|
||||
|
||||
@@ -57,8 +57,21 @@ u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, Display& display,
|
||||
// Set default speed limit to 100%.
|
||||
*out_speed_scale = 1.0f;
|
||||
|
||||
// If no layers are visible, skip the logic. Acquiring and holding buffers here would
|
||||
// consume the producer's queue without ever presenting.
|
||||
bool any_visible = false;
|
||||
for (auto& layer : display.stack.layers) {
|
||||
if (layer->visible) {
|
||||
any_visible = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!any_visible) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Wait for the previous composite, bounding the number of in-flight composites.
|
||||
nvdisp.WaitForComposite();
|
||||
this->ReleaseFramebuffersLocked(display);
|
||||
|
||||
// Determine the number of vsync periods to wait before composing again.
|
||||
std::optional<s32> swap_interval{};
|
||||
@@ -152,6 +165,13 @@ u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, Display& display,
|
||||
// Advance by 1 frame (60 FPS compositing)
|
||||
m_frame_number += 1;
|
||||
|
||||
// Release framebuffers once the frame has been handed to the compositor. This happens
|
||||
// within the same vsync period as the acquire (release_frame_number is checked against
|
||||
// the advanced counter), so the producer gets its buffers back immediately instead of
|
||||
// losing a queue slot for a whole frame.
|
||||
// TODO: support release fences; releasing before the composite has finished can tear.
|
||||
this->ReleaseFramebuffersLocked(display);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -40,12 +40,6 @@ bool IsConnectionBased(Type type) {
|
||||
}
|
||||
}
|
||||
|
||||
// Size of a real BSD sockaddr_in. The guest SockAddrIn struct is padded to 0x100 so that longer
|
||||
// input addresses can be read, but an address handed back to the game is always this long.
|
||||
// Reporting 0x100 lets a game that trusts the length copy 240 bytes past its 16-byte sockaddr
|
||||
// (suspected cause of Crysis Remastered crashing ~30 s after its getsockname() call).
|
||||
constexpr size_t GuestSockAddrInSize = 16;
|
||||
|
||||
template <typename T>
|
||||
T GetValue(std::span<const u8> buffer) {
|
||||
T t{};
|
||||
@@ -661,9 +655,6 @@ std::pair<s32, Errno> BSD_USA::AcceptImpl(s32 fd, std::vector<u8>& write_buffer)
|
||||
new_descriptor.is_connection_based = descriptor.is_connection_based;
|
||||
|
||||
const SockAddrIn guest_addr_in = Translate(result.sockaddr_in);
|
||||
if (write_buffer.size() > GuestSockAddrInSize) {
|
||||
write_buffer.resize(GuestSockAddrInSize);
|
||||
}
|
||||
PutValue(write_buffer, guest_addr_in);
|
||||
|
||||
return {new_fd, Errno::SUCCESS};
|
||||
@@ -723,8 +714,8 @@ Errno BSD_USA::GetPeerNameImpl(s32 fd, std::vector<u8>& write_buffer) {
|
||||
}
|
||||
const SockAddrIn guest_addrin = Translate(addr_in);
|
||||
|
||||
// The reported length must be that of a real sockaddr_in, not of the padded guest struct.
|
||||
write_buffer.resize(GuestSockAddrInSize);
|
||||
ASSERT(write_buffer.size() >= sizeof(guest_addrin));
|
||||
write_buffer.resize(sizeof(guest_addrin));
|
||||
PutValue(write_buffer, guest_addrin);
|
||||
return Translate(bsd_errno);
|
||||
}
|
||||
@@ -745,8 +736,8 @@ Errno BSD_USA::GetSockNameImpl(s32 fd, std::vector<u8>& write_buffer) {
|
||||
}
|
||||
const SockAddrIn guest_addrin = Translate(addr_in);
|
||||
|
||||
// The reported length must be that of a real sockaddr_in, not of the padded guest struct.
|
||||
write_buffer.resize(GuestSockAddrInSize);
|
||||
ASSERT(write_buffer.size() >= sizeof(guest_addrin));
|
||||
write_buffer.resize(sizeof(guest_addrin));
|
||||
PutValue(write_buffer, guest_addrin);
|
||||
return Translate(bsd_errno);
|
||||
}
|
||||
@@ -958,9 +949,8 @@ std::pair<s32, Errno> BSD_USA::RecvFromImpl(s32 fd, u32 flags, std::vector<u8>&
|
||||
if (ret < 0) {
|
||||
addr.clear();
|
||||
} else {
|
||||
ASSERT(addr.size() >= GuestSockAddrInSize);
|
||||
ASSERT(addr.size() >= 16);
|
||||
const SockAddrIn result = Translate(addr_in);
|
||||
addr.resize(GuestSockAddrInSize);
|
||||
PutValue(addr, result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -563,8 +563,10 @@ void RecordShaderReadBarrier(Scheduler& scheduler, const ImageView& image_view)
|
||||
});
|
||||
}
|
||||
|
||||
void BeginRenderPass(vk::CommandBuffer& cmdbuf, VkRenderPass render_pass,
|
||||
VkFramebuffer framebuffer_handle, VkExtent2D render_area) {
|
||||
void BeginRenderPass(vk::CommandBuffer& cmdbuf, const Framebuffer* framebuffer) {
|
||||
const VkRenderPass render_pass = framebuffer->RenderPass();
|
||||
const VkFramebuffer framebuffer_handle = framebuffer->Handle();
|
||||
const VkExtent2D render_area = framebuffer->RenderArea();
|
||||
const VkRenderPassBeginInfo renderpass_bi{
|
||||
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
||||
.pNext = nullptr,
|
||||
@@ -677,67 +679,27 @@ void BlitImageHelper::BlitColor(const Framebuffer* dst_framebuffer, const ImageV
|
||||
void BlitImageHelper::BlitColor(const Framebuffer* dst_framebuffer, VkImageView src_image_view,
|
||||
VkImage src_image, VkSampler src_sampler,
|
||||
const Region2D& dst_region, const Region2D& src_region,
|
||||
const Extent3D& src_size,
|
||||
const std::optional<VkRect2D>& scissor) {
|
||||
const Extent3D& src_size) {
|
||||
const BlitImagePipelineKey key{
|
||||
.renderpass = dst_framebuffer->RenderPass(),
|
||||
.operation = Tegra::Engines::Fermi2D::Operation::SrcCopy,
|
||||
};
|
||||
const VkPipelineLayout layout = *one_texture_pipeline_layout;
|
||||
const VkPipeline pipeline = FindOrEmplaceColorPipeline(key);
|
||||
|
||||
// Clip the destination rectangle to the scissor; the viewport keeps the full rectangle so
|
||||
// the texture coordinates are unchanged.
|
||||
std::optional<VkRect2D> clip;
|
||||
if (scissor) {
|
||||
const s64 x0 = (std::max)(s64{(std::min)(dst_region.start.x, dst_region.end.x)},
|
||||
s64{scissor->offset.x});
|
||||
const s64 y0 = (std::max)(s64{(std::min)(dst_region.start.y, dst_region.end.y)},
|
||||
s64{scissor->offset.y});
|
||||
const s64 x1 = (std::min)(s64{(std::max)(dst_region.start.x, dst_region.end.x)},
|
||||
s64{scissor->offset.x} + scissor->extent.width);
|
||||
const s64 y1 = (std::min)(s64{(std::max)(dst_region.start.y, dst_region.end.y)},
|
||||
s64{scissor->offset.y} + scissor->extent.height);
|
||||
if (x1 <= x0 || y1 <= y0) {
|
||||
return; // Fully scissored out.
|
||||
}
|
||||
clip = VkRect2D{
|
||||
.offset = {static_cast<s32>(x0), static_cast<s32>(y0)},
|
||||
.extent = {static_cast<u32>(x1 - x0), static_cast<u32>(y1 - y0)},
|
||||
};
|
||||
}
|
||||
|
||||
// Read the framebuffer now: by the time the worker runs this, the texture cache may have
|
||||
// retired it (moved into its delayed-destruction ring), leaving a null handle behind - Turnip
|
||||
// then crashed in vkCmdBeginRenderPass (Crysis Remastered, DrawTexture).
|
||||
const VkRenderPass render_pass = dst_framebuffer->RenderPass();
|
||||
const VkFramebuffer framebuffer_handle = dst_framebuffer->Handle();
|
||||
const VkExtent2D render_area = dst_framebuffer->RenderArea();
|
||||
scheduler.RequestOutsideRenderPassOperationContext();
|
||||
scheduler.Record([this, render_pass, framebuffer_handle, render_area, src_image_view,
|
||||
src_image, src_sampler, dst_region, src_region, src_size, pipeline, layout,
|
||||
clip](vk::CommandBuffer cmdbuf) {
|
||||
// Images stay in GENERAL everywhere (the descriptor below says so too): only make the
|
||||
// earlier writes visible. Moving the source to SHADER_READ_ONLY_OPTIMAL left it there
|
||||
// for good, so every later render pass used it in the wrong layout.
|
||||
TransitionImageLayout(cmdbuf, src_image, VK_IMAGE_LAYOUT_GENERAL);
|
||||
BeginRenderPass(cmdbuf, render_pass, framebuffer_handle, render_area);
|
||||
scheduler.Record([this, dst_framebuffer, src_image_view, src_image, src_sampler, dst_region,
|
||||
src_region, src_size, pipeline, layout](vk::CommandBuffer cmdbuf) {
|
||||
TransitionImageLayout(cmdbuf, src_image, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
BeginRenderPass(cmdbuf, dst_framebuffer);
|
||||
const VkDescriptorSet descriptor_set = one_texture_descriptor_allocator.Commit();
|
||||
UpdateOneTextureDescriptorSet(device, descriptor_set, src_sampler, src_image_view);
|
||||
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
||||
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptor_set,
|
||||
nullptr);
|
||||
BindBlitState(cmdbuf, layout, dst_region, src_region, src_size);
|
||||
if (clip) {
|
||||
cmdbuf.SetScissor(0, *clip);
|
||||
}
|
||||
cmdbuf.Draw(3, 1, 0, 0);
|
||||
cmdbuf.EndRenderPass();
|
||||
});
|
||||
// The blit set its own pipeline, viewport and scissor: make the next draw set its own again,
|
||||
// as every other helper here does. Without this the next draw kept the blit's viewport and
|
||||
// scissor: Crysis Remastered drew its 256x256 minimap map over the whole screen.
|
||||
scheduler.InvalidateState();
|
||||
}
|
||||
|
||||
void BlitImageHelper::BlitImpl(const Framebuffer* dst_framebuffer,
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <deque>
|
||||
#include <optional>
|
||||
#include <span>
|
||||
|
||||
#include "video_core/engines/fermi_2d.h"
|
||||
@@ -79,12 +78,9 @@ public:
|
||||
Tegra::Engines::Fermi2D::Filter filter,
|
||||
Tegra::Engines::Fermi2D::Operation operation);
|
||||
|
||||
/// @param scissor Optional clip rectangle in framebuffer pixels (DrawTexture honours the
|
||||
/// guest scissor like any other draw).
|
||||
void BlitColor(const Framebuffer* dst_framebuffer, VkImageView src_image_view,
|
||||
VkImage src_image, VkSampler src_sampler, const Region2D& dst_region,
|
||||
const Region2D& src_region, const Extent3D& src_size,
|
||||
const std::optional<VkRect2D>& scissor = std::nullopt);
|
||||
const Region2D& src_region, const Extent3D& src_size);
|
||||
|
||||
void BlitColorMSAA(const Framebuffer* dst_framebuffer, const ImageView& src_image_view,
|
||||
const Region2D& dst_region, const Region2D& src_region);
|
||||
|
||||
@@ -393,35 +393,8 @@ void RasterizerVulkan::DrawTexture() {
|
||||
.y = ScaleSrc(draw_texture_state.src_y1)}};
|
||||
Extent3D src_size = {static_cast<u32>(ScaleSrc(texture.size.width)),
|
||||
static_cast<u32>(ScaleSrc(texture.size.height)), texture.size.depth};
|
||||
// DrawTexture rectangles go through the fragment pipeline, scissor included.
|
||||
std::optional<VkRect2D> scissor;
|
||||
if (maxwell3d->regs.scissor_test[0].enable) {
|
||||
u32 up_scale = 1;
|
||||
u32 down_shift = 0;
|
||||
if (dst_rescaling) {
|
||||
up_scale = Settings::values.resolution_info.up_scale;
|
||||
down_shift = Settings::values.resolution_info.down_shift;
|
||||
}
|
||||
scissor = GetScissorState(maxwell3d->regs, 0, up_scale, down_shift);
|
||||
}
|
||||
|
||||
// Drawing a texture 1:1 onto itself without blending changes nothing on hardware, but here
|
||||
// it samples the image the render pass is writing to: undefined in Vulkan, and on tiled GPUs
|
||||
// it reads whatever the image memory last held. Crysis Remastered does this every frame for
|
||||
// its post-processing buffers (suspected cause of its map covering the whole screen).
|
||||
const auto& fb_images = framebuffer->Images();
|
||||
const bool src_is_target =
|
||||
std::find(fb_images.begin(), fb_images.begin() + framebuffer->NumImages(),
|
||||
texture.ImageHandle()) != fb_images.begin() + framebuffer->NumImages();
|
||||
if (src_is_target && src_rescaling == dst_rescaling &&
|
||||
src_region.start.x == dst_region.start.x && src_region.start.y == dst_region.start.y &&
|
||||
src_region.end.x == dst_region.end.x && src_region.end.y == dst_region.end.y &&
|
||||
maxwell3d->regs.blend.enable[0] == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
blit_image.BlitColor(framebuffer, texture.RenderTarget(), texture.ImageHandle(),
|
||||
sampler->Handle(), dst_region, src_region, src_size, scissor);
|
||||
sampler->Handle(), dst_region, src_region, src_size);
|
||||
}
|
||||
|
||||
void RasterizerVulkan::Clear(u32 layer_count) {
|
||||
|
||||
Reference in New Issue
Block a user