mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-08-18 22:23:35 +00:00
Compare commits
30 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7b6eb6fb7a | |||
| 36010d2538 | |||
| c6189c791b | |||
| 2950091828 | |||
| 89fc2b94e6 | |||
| 88eb1aab39 | |||
| 624aff4e92 | |||
| 0a8c413708 | |||
| 402fa3ae93 | |||
| 6a5f86f201 | |||
| 8d78acf8b6 | |||
| 7ec09305d0 | |||
| 71d0b4f79b | |||
| d7e3fd7fe8 | |||
| 5a10e95188 | |||
| e78ab8eeef | |||
| 0c3d3eb19d | |||
| 39ae39293f | |||
| d44ce7b93b | |||
| ea6344b031 | |||
| 3a7392d4be | |||
| 7d591b3bd9 | |||
| 144e20800f | |||
| a7377f552a | |||
| 39138fbdd2 | |||
| cd9527072d | |||
| ffdaf7369a | |||
| 5113f503d1 | |||
| a5f1c2bcb0 | |||
| 2e432c9d17 |
@@ -8,20 +8,26 @@
|
||||
include(GetSCMRev)
|
||||
|
||||
function(get_timestamp _var)
|
||||
string(TIMESTAMP timestamp UTC)
|
||||
set(${_var} "${timestamp}" PARENT_SCOPE)
|
||||
string(TIMESTAMP timestamp UTC)
|
||||
set(${_var} "${timestamp}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
get_timestamp(BUILD_DATE)
|
||||
|
||||
if (DEFINED GIT_RELEASE)
|
||||
set(BUILD_VERSION "${GIT_TAG}")
|
||||
set(GIT_REFSPEC "${GIT_RELEASE}")
|
||||
set(IS_DEV_BUILD false)
|
||||
set(BUILD_VERSION "${GIT_TAG}")
|
||||
set(GIT_REFSPEC "${GIT_RELEASE}")
|
||||
set(IS_DEV_BUILD false)
|
||||
else()
|
||||
string(SUBSTRING ${GIT_COMMIT} 0 10 BUILD_VERSION)
|
||||
set(BUILD_VERSION "${BUILD_VERSION}-${GIT_REFSPEC}")
|
||||
set(IS_DEV_BUILD true)
|
||||
string(SUBSTRING ${GIT_COMMIT} 0 10 BUILD_VERSION)
|
||||
set(BUILD_VERSION "${BUILD_VERSION}-${GIT_REFSPEC}")
|
||||
set(IS_DEV_BUILD true)
|
||||
endif()
|
||||
|
||||
if (NIGHTLY_BUILD)
|
||||
set(IS_NIGHTLY_BUILD true)
|
||||
else()
|
||||
set(IS_NIGHTLY_BUILD false)
|
||||
endif()
|
||||
|
||||
set(GIT_DESC ${BUILD_VERSION})
|
||||
@@ -34,11 +40,11 @@ set(BUILD_AUTO_UPDATE_WEBSITE "https://github.com")
|
||||
set(BUILD_AUTO_UPDATE_API "http://api.github.com")
|
||||
|
||||
if (NIGHTLY_BUILD)
|
||||
set(BUILD_AUTO_UPDATE_REPO "Eden-CI/Nightly")
|
||||
set(REPO_NAME "Eden Nightly")
|
||||
set(BUILD_AUTO_UPDATE_REPO "Eden-CI/Nightly")
|
||||
set(REPO_NAME "Eden Nightly")
|
||||
else()
|
||||
set(BUILD_AUTO_UPDATE_REPO "eden-emulator/Releases")
|
||||
set(REPO_NAME "Eden")
|
||||
set(BUILD_AUTO_UPDATE_REPO "eden-emulator/Releases")
|
||||
set(REPO_NAME "Eden")
|
||||
endif()
|
||||
|
||||
set(BUILD_ID ${GIT_REFSPEC})
|
||||
|
||||
+5
@@ -29,11 +29,16 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting {
|
||||
RENDERER_DEBUG("debug"),
|
||||
RENDERER_PATCH_OLD_QCOM_DRIVERS("patch_old_qcom_drivers"),
|
||||
RENDERER_VERTEX_INPUT_DYNAMIC_STATE("vertex_input_dynamic_state"),
|
||||
RENDERER_PROVOKING_VERTEX("provoking_vertex"),
|
||||
RENDERER_DESCRIPTOR_INDEXING("descriptor_indexing"),
|
||||
RENDERER_SAMPLE_SHADING("sample_shading"),
|
||||
PICTURE_IN_PICTURE("picture_in_picture"),
|
||||
USE_CUSTOM_RTC("custom_rtc_enabled"),
|
||||
BLACK_BACKGROUNDS("black_backgrounds"),
|
||||
|
||||
ENABLE_FOLDER_BUTTON("enable_folder_button"),
|
||||
ENABLE_QLAUNCH_BUTTON("enable_qlaunch_button"),
|
||||
|
||||
ENABLE_UPDATE_CHECKS("enable_update_checks"),
|
||||
JOYSTICK_REL_CENTER("joystick_rel_center"),
|
||||
DPAD_SLIDE("dpad_slide"),
|
||||
|
||||
@@ -16,7 +16,6 @@ enum class IntSetting(override val key: String) : AbstractIntSetting {
|
||||
RENDERER_BACKEND("backend"),
|
||||
RENDERER_VRAM_USAGE_MODE("vram_usage_mode"),
|
||||
RENDERER_NVDEC_EMULATION("nvdec_emulation"),
|
||||
RENDERER_ASTC_DECODE_METHOD("accelerate_astc"),
|
||||
RENDERER_ASTC_RECOMPRESSION("astc_recompression"),
|
||||
RENDERER_ACCURACY("gpu_accuracy"),
|
||||
RENDERER_RESOLUTION("resolution_setup"),
|
||||
|
||||
+33
-10
@@ -60,6 +60,11 @@ abstract class SettingsItem(
|
||||
return NativeInput.getStyleIndex(0) != NpadStyleIndex.Handheld
|
||||
}
|
||||
|
||||
// Can't edit enable_qlaunch_button if firmware is not available
|
||||
if (setting.key == BooleanSetting.ENABLE_QLAUNCH_BUTTON.key) {
|
||||
return NativeLibrary.isFirmwareAvailable()
|
||||
}
|
||||
|
||||
// Can't edit settings that aren't saveable in per-game config even if they are switchable
|
||||
if (NativeConfig.isPerGameConfigLoaded() && !setting.isSaveable) {
|
||||
return false
|
||||
@@ -143,12 +148,25 @@ abstract class SettingsItem(
|
||||
)
|
||||
put(
|
||||
SwitchSetting(
|
||||
|
||||
BooleanSetting.RENDERER_PROVOKING_VERTEX,
|
||||
titleId = R.string.provoking_vertex,
|
||||
descriptionId = R.string.provoking_vertex_description
|
||||
)
|
||||
)
|
||||
put(
|
||||
SwitchSetting(
|
||||
BooleanSetting.RENDERER_VERTEX_INPUT_DYNAMIC_STATE,
|
||||
titleId = R.string.vertex_input_dynamic_state,
|
||||
descriptionId = R.string.vertex_input_dynamic_state_description
|
||||
)
|
||||
)
|
||||
put(
|
||||
SwitchSetting(
|
||||
BooleanSetting.RENDERER_DESCRIPTOR_INDEXING,
|
||||
titleId = R.string.descriptor_indexing,
|
||||
descriptionId = R.string.descriptor_indexing_description
|
||||
)
|
||||
)
|
||||
put(
|
||||
SliderSetting(
|
||||
IntSetting.RENDERER_SAMPLE_SHADING,
|
||||
@@ -307,15 +325,6 @@ abstract class SettingsItem(
|
||||
valuesId = R.array.rendererNvdecValues
|
||||
)
|
||||
)
|
||||
put(
|
||||
SingleChoiceSetting(
|
||||
IntSetting.RENDERER_ASTC_DECODE_METHOD,
|
||||
titleId = R.string.accelerate_astc,
|
||||
descriptionId = R.string.accelerate_astc_description,
|
||||
choicesId = R.array.astcDecodingMethodNames,
|
||||
valuesId = R.array.astcDecodingMethodValues
|
||||
)
|
||||
)
|
||||
put(
|
||||
SingleChoiceSetting(
|
||||
IntSetting.RENDERER_ASTC_RECOMPRESSION,
|
||||
@@ -781,6 +790,20 @@ abstract class SettingsItem(
|
||||
descriptionId = R.string.enable_update_checks_description,
|
||||
)
|
||||
)
|
||||
put(
|
||||
SwitchSetting(
|
||||
BooleanSetting.ENABLE_FOLDER_BUTTON,
|
||||
titleId = R.string.enable_folder_button,
|
||||
descriptionId = R.string.enable_folder_button_description,
|
||||
)
|
||||
)
|
||||
put(
|
||||
SwitchSetting(
|
||||
BooleanSetting.ENABLE_QLAUNCH_BUTTON,
|
||||
titleId = R.string.enable_qlaunch_button,
|
||||
descriptionId = R.string.enable_qlaunch_button_description,
|
||||
)
|
||||
)
|
||||
put(
|
||||
SingleChoiceSetting(
|
||||
IntSetting.APP_LANGUAGE,
|
||||
|
||||
+9
-1
@@ -268,7 +268,6 @@ class SettingsFragmentPresenter(
|
||||
add(IntSetting.DMA_ACCURACY.key)
|
||||
add(IntSetting.MAX_ANISOTROPY.key)
|
||||
add(IntSetting.RENDERER_VRAM_USAGE_MODE.key)
|
||||
add(IntSetting.RENDERER_ASTC_DECODE_METHOD.key)
|
||||
add(IntSetting.RENDERER_ASTC_RECOMPRESSION.key)
|
||||
|
||||
add(BooleanSetting.SYNC_MEMORY_OPERATIONS.key)
|
||||
@@ -290,6 +289,8 @@ class SettingsFragmentPresenter(
|
||||
|
||||
add(IntSetting.RENDERER_DYNA_STATE.key)
|
||||
add(BooleanSetting.RENDERER_VERTEX_INPUT_DYNAMIC_STATE.key)
|
||||
add(BooleanSetting.RENDERER_PROVOKING_VERTEX.key)
|
||||
add(BooleanSetting.RENDERER_DESCRIPTOR_INDEXING.key)
|
||||
add(IntSetting.RENDERER_SAMPLE_SHADING.key)
|
||||
|
||||
add(HeaderSetting(R.string.display))
|
||||
@@ -1189,6 +1190,13 @@ class SettingsFragmentPresenter(
|
||||
descriptionId = R.string.use_black_backgrounds_description
|
||||
)
|
||||
)
|
||||
|
||||
add(HeaderSetting(R.string.buttons))
|
||||
add(BooleanSetting.ENABLE_FOLDER_BUTTON.key)
|
||||
add(BooleanSetting.ENABLE_QLAUNCH_BUTTON.key)
|
||||
if (!NativeLibrary.isFirmwareAvailable()) {
|
||||
BooleanSetting.ENABLE_QLAUNCH_BUTTON.setBoolean(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package org.yuzu.yuzu_emu.ui
|
||||
@@ -13,6 +13,7 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.PopupMenu
|
||||
import android.widget.Toast
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.ViewCompat
|
||||
@@ -27,10 +28,14 @@ import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
import org.yuzu.yuzu_emu.HomeNavigationDirections
|
||||
import org.yuzu.yuzu_emu.NativeLibrary
|
||||
import org.yuzu.yuzu_emu.R
|
||||
import org.yuzu.yuzu_emu.YuzuApplication
|
||||
import org.yuzu.yuzu_emu.adapters.GameAdapter
|
||||
import org.yuzu.yuzu_emu.databinding.FragmentGamesBinding
|
||||
import org.yuzu.yuzu_emu.features.settings.model.BooleanSetting
|
||||
import org.yuzu.yuzu_emu.model.AppletInfo
|
||||
import org.yuzu.yuzu_emu.model.Game
|
||||
import org.yuzu.yuzu_emu.model.GamesViewModel
|
||||
import org.yuzu.yuzu_emu.model.HomeViewModel
|
||||
@@ -173,10 +178,16 @@ class GamesFragment : Fragment() {
|
||||
|
||||
setupTopView()
|
||||
|
||||
updateButtonsVisibility()
|
||||
|
||||
binding.addDirectory.setOnClickListener {
|
||||
getGamesDirectory.launch(Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).data)
|
||||
}
|
||||
|
||||
binding.launchQlaunch?.setOnClickListener {
|
||||
launchQLaunch()
|
||||
}
|
||||
|
||||
setInsets()
|
||||
}
|
||||
|
||||
@@ -445,6 +456,47 @@ class GamesFragment : Fragment() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun launchQLaunch() {
|
||||
try {
|
||||
val appletPath = NativeLibrary.getAppletLaunchPath(AppletInfo.QLaunch.entryId)
|
||||
if (appletPath.isEmpty()) {
|
||||
Toast.makeText(
|
||||
requireContext(),
|
||||
R.string.applets_error_applet,
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
return
|
||||
}
|
||||
|
||||
NativeLibrary.setCurrentAppletId(AppletInfo.QLaunch.appletId)
|
||||
|
||||
val qlaunchGame = Game(
|
||||
title = getString(R.string.qlaunch_applet),
|
||||
path = appletPath
|
||||
)
|
||||
|
||||
val action = HomeNavigationDirections.actionGlobalEmulationActivity(qlaunchGame)
|
||||
findNavController().navigate(action)
|
||||
} catch (e: Exception) {
|
||||
Toast.makeText(
|
||||
requireContext(),
|
||||
"Failed to launch QLaunch: ${e.message}",
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateButtonsVisibility() {
|
||||
val showQLaunch = BooleanSetting.ENABLE_QLAUNCH_BUTTON.getBoolean()
|
||||
val showFolder = BooleanSetting.ENABLE_FOLDER_BUTTON.getBoolean()
|
||||
val isFirmwareAvailable = NativeLibrary.isFirmwareAvailable()
|
||||
|
||||
val shouldShowQLaunch = showQLaunch && isFirmwareAvailable
|
||||
binding.launchQlaunch.visibility = if (shouldShowQLaunch) View.VISIBLE else View.GONE
|
||||
|
||||
binding.addDirectory.visibility = if (showFolder) View.VISIBLE else View.GONE
|
||||
}
|
||||
|
||||
private fun setInsets() =
|
||||
ViewCompat.setOnApplyWindowInsetsListener(
|
||||
binding.root
|
||||
@@ -498,6 +550,13 @@ class GamesFragment : Fragment() {
|
||||
mlpFab.rightMargin = rightInset + fabPadding
|
||||
binding.addDirectory.layoutParams = mlpFab
|
||||
|
||||
binding.launchQlaunch?.let { qlaunchButton ->
|
||||
val mlpQLaunch = qlaunchButton.layoutParams as ViewGroup.MarginLayoutParams
|
||||
mlpQLaunch.leftMargin = leftInset + fabPadding
|
||||
mlpQLaunch.bottomMargin = barInsets.bottom + fabPadding
|
||||
qlaunchButton.layoutParams = mlpQLaunch
|
||||
}
|
||||
|
||||
val navInsets = windowInsets.getInsets(WindowInsetsCompat.Type.navigationBars())
|
||||
val gestureInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemGestures())
|
||||
val bottomInset = maxOf(navInsets.bottom, gestureInsets.bottom, cutoutInsets.bottom)
|
||||
|
||||
@@ -65,6 +65,10 @@ namespace AndroidSettings {
|
||||
Settings::Setting<s32> app_language{linkage, 0, "app_language", Settings::Category::Android};
|
||||
Settings::Setting<bool> enable_update_checks{linkage, true, "enable_update_checks",
|
||||
Settings::Category::Android};
|
||||
Settings::Setting<bool> enable_folder_button{linkage, true, "enable_folder_button",
|
||||
Settings::Category::Android};
|
||||
Settings::Setting<bool> enable_qlaunch_button{linkage, false, "enable_qlaunch_button",
|
||||
Settings::Category::Android};
|
||||
|
||||
// Input/performance overlay settings
|
||||
std::vector<OverlayControlData> overlay_control_data;
|
||||
|
||||
@@ -1615,22 +1615,14 @@ JNIEXPORT jboolean JNICALL Java_org_yuzu_yuzu_1emu_NativeLibrary_isNightlyBuild(
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef ENABLE_UPDATE_CHECKER
|
||||
|
||||
|
||||
JNIEXPORT jobjectArray JNICALL Java_org_yuzu_yuzu_1emu_NativeLibrary_checkForUpdate(
|
||||
JNIEnv* env,
|
||||
jobject obj) {
|
||||
const bool is_prerelease = ((strstr(Common::g_build_version, "pre-alpha") != nullptr) ||
|
||||
(strstr(Common::g_build_version, "alpha") != nullptr) ||
|
||||
(strstr(Common::g_build_version, "beta") != nullptr) ||
|
||||
(strstr(Common::g_build_version, "rc") != nullptr));
|
||||
const std::optional<UpdateChecker::Update> release =
|
||||
UpdateChecker::GetLatestRelease(is_prerelease);
|
||||
|
||||
if (!release || release->tag == Common::g_build_version) {
|
||||
return nullptr;
|
||||
}
|
||||
std::optional<UpdateChecker::Update> release = UpdateChecker::GetUpdate();
|
||||
if (!release) return nullptr;
|
||||
|
||||
const std::string tag = release->tag;
|
||||
const std::string name = release->name;
|
||||
|
||||
@@ -220,6 +220,23 @@
|
||||
android:textColor="?attr/colorOnPrimary"
|
||||
app:backgroundTint="?attr/colorPrimary"
|
||||
app:iconTint="?attr/colorOnPrimary"
|
||||
app:rippleColor="#99FFFFFF"
|
||||
/>
|
||||
|
||||
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
||||
android:id="@+id/launch_qlaunch"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="16dp"
|
||||
android:contentDescription="Launch QLaunch"
|
||||
android:text="@string/qlaunch_applet"
|
||||
app:icon="@drawable/ic_home"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
android:textColor="?attr/colorOnPrimary"
|
||||
app:backgroundTint="?attr/colorPrimary"
|
||||
app:iconTint="?attr/colorOnPrimary"
|
||||
app:rippleColor="#99FFFFFF"
|
||||
/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -214,6 +214,22 @@
|
||||
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
|
||||
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
||||
android:id="@+id/launch_qlaunch"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="16dp"
|
||||
android:contentDescription="Launch QLaunch"
|
||||
android:text="@string/qlaunch_applet"
|
||||
app:icon="@drawable/ic_home"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
android:textColor="?attr/colorOnPrimary"
|
||||
app:backgroundTint="?attr/colorPrimary"
|
||||
app:iconTint="?attr/colorOnPrimary"
|
||||
app:rippleColor="#99FFFFFF"
|
||||
/>
|
||||
|
||||
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
||||
android:id="@+id/add_directory"
|
||||
android:layout_width="wrap_content"
|
||||
@@ -227,6 +243,7 @@
|
||||
android:textColor="?attr/colorOnPrimary"
|
||||
app:backgroundTint="?attr/colorPrimary"
|
||||
app:iconTint="?attr/colorOnPrimary"
|
||||
app:rippleColor="#99FFFFFF"
|
||||
/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -511,7 +511,10 @@
|
||||
<string name="disabled">معطل</string>
|
||||
<string name="vertex_input_dynamic_state">حالة ديناميكية لإدخال الرأس</string>
|
||||
<string name="vertex_input_dynamic_state_description">يتيح ميزة الحالة الديناميكية لإدخال الرأس لتحسين الجودة والأداء.</string>
|
||||
|
||||
<string name="provoking_vertex">الرأس المثير</string>
|
||||
<string name="provoking_vertex_description">يحسن الإضاءة ومعالجة الرؤوس في بعض الألعاب. مدعوم فقط على وحدات معالجة الرسومات Vulkan 1.0+.</string>
|
||||
<string name="descriptor_indexing">فهرسة الوصف</string>
|
||||
<string name="descriptor_indexing_description">يحسن معالجة النسيج والمخزن المؤقت، بالإضافة إلى طبقة الترجمة Maxwell. مدعوم من بعض وحدات معالجة الرسومات Vulkan 1.1 وجميع وحدات معالجة الرسومات Vulkan 1.2+.</string>
|
||||
<string name="sample_shading_fraction">تظليل العينة</string>
|
||||
<string name="sample_shading_fraction_description">يسمح هذا الخيار بتنفيذ مُظلل الأجزاء لكل عينة في جزء متعدد العينات بدلاً من تنفيذه مرة واحدة لكل جزء. يُحسّن هذا من جودة الرسومات على حساب بعض الأداء.</string>
|
||||
|
||||
|
||||
@@ -368,7 +368,10 @@
|
||||
<string name="renderer_asynchronous_shaders_description">کۆمپایلکردنی شادەرەکان بەشێوەی ناڕێک. ئەمە ڕەنگە کەمکردنەوەی ستەتەر بکات بەڵام لەوانەیە هەڵەش دروست بکات.</string>
|
||||
<string name="dyna_state">الحالة الديناميكية الممتدة</string>
|
||||
<string name="disabled">ناچالاک</string>
|
||||
|
||||
<string name="provoking_vertex">الرأس المثير</string>
|
||||
<string name="provoking_vertex_description">يحسن الإضاءة ومعالجة الرؤوس في بعض الألعاب. مدعوم فقط على وحدات معالجة الرسومات التي تدعم فولكان 1.0+.</string>
|
||||
<string name="descriptor_indexing">فهرسة الواصفات</string>
|
||||
<string name="descriptor_indexing_description">يحسن معالجة القوام والمخازن المؤقتة، بالإضافة إلى طبقة ترجمة ماكسويل. مدعوم من قبل بعض وحدات معالجة الرسومات التي تدعم فولكان 1.1 وجميع وحدات معالجة الرسومات التي تدعم فولكان 1.2+.</string>
|
||||
<string name="display">پیشاندان</string>
|
||||
|
||||
<string name="renderer_screen_layout">ڕێکخستنی شاشە</string>
|
||||
|
||||
@@ -493,7 +493,10 @@
|
||||
<string name="disabled">Vypnuto</string>
|
||||
<string name="vertex_input_dynamic_state">Dynamický stav vstupu vrcholů (Vertex Input)</string>
|
||||
<string name="vertex_input_dynamic_state_description">Aktivuje funkci dynamického stavu vstupu vrcholů (Vertex Input Dynamic State) pro lepší kvalitu a výkon.</string>
|
||||
|
||||
<string name="provoking_vertex">Určující vrchol</string>
|
||||
<string name="provoking_vertex_description">Zlepšuje osvětlení a zpracování vrcholů v některých hrách. Podporováno pouze na GPU s API Vulkan 1.0+.</string>
|
||||
<string name="descriptor_indexing">Indexování deskriptorů</string>
|
||||
<string name="descriptor_indexing_description">Zlepšuje zpracování textur a bufferů, stejně jako překladovou vrstvu architektury Maxwell. Podporováno některými GPU s API Vulkan 1.1 a všemi GPU s API Vulkan 1.2+.</string>
|
||||
<string name="display">Zobrazení</string>
|
||||
|
||||
<string name="renderer_screen_layout">Orientace</string>
|
||||
|
||||
@@ -491,7 +491,10 @@ Wird der Handheld-Modus verwendet, verringert es die Auflösung und erhöht die
|
||||
<string name="disabled">Deaktiviert</string>
|
||||
<string name="vertex_input_dynamic_state">Vertex Input Dynamic State</string>
|
||||
<string name="vertex_input_dynamic_state_description">Aktiviert die Funktion \"Vertex Input Dynamic State\" für bessere Qualität und Leistung.</string>
|
||||
|
||||
<string name="provoking_vertex">Provokanter Vertex</string>
|
||||
<string name="provoking_vertex_description">Verbessert die Beleuchtung und die Vertex-Verarbeitung in einigen Spielen. Wird nur von GPUs mit Vulkan 1.0+ unterstützt.</string>
|
||||
<string name="descriptor_indexing">Deskriptor-Indizierung</string>
|
||||
<string name="descriptor_indexing_description">Verbessert die Textur- und Puffer-Verarbeitung sowie die Maxwell-Übersetzungsschicht. Wird von einigen Vulkan 1.1-GPUs und allen Vulkan 1.2+-GPUs unterstützt.</string>
|
||||
<string name="sample_shading_fraction">Sample Shading</string>
|
||||
<string name="sample_shading_fraction_description">Ermöglicht es dem Fragment-Shader, in einem Multisample-Fragment pro Sample anstatt einmal pro Fragment ausgeführt zu werden. Verbessert die Grafikqualität auf Kosten der Leistung.</string>
|
||||
|
||||
|
||||
@@ -425,7 +425,10 @@
|
||||
<string name="renderer_asynchronous_shaders_description">Compila los shaders de forma asíncrona. Esto puede reducir los tirones, pero también puede introducir errores gráficos.</string>
|
||||
<string name="dyna_state">Estado dinámico extendido</string>
|
||||
<string name="disabled">Desactivado</string>
|
||||
|
||||
<string name="provoking_vertex">Vértice provocante</string>
|
||||
<string name="provoking_vertex_description">Mejora la iluminación y el manejo de vértices en ciertos juegos. Solo es compatible con las GPU Vulkan 1.0+.</string>
|
||||
<string name="descriptor_indexing">Indexación del descriptor</string>
|
||||
<string name="descriptor_indexing_description">Mejora la textura y el manejo del búfer, así como la capa de traducción Maxwell. Compatible con algunas GPU Vulkan 1.1 y todas las GPU Vulkan 1.2+.</string>
|
||||
<string name="display">Pantalla</string>
|
||||
|
||||
<string name="renderer_screen_layout">Orientación</string>
|
||||
|
||||
@@ -73,7 +73,10 @@
|
||||
<string name="uninstall_firmware_description">حذف فرمور آن را از دستگاه پاک میکند و ممکن است بر سازگاری بازیها تأثیر بگذارد</string>
|
||||
<string name="firmware_uninstalling">در حال حذف فرمور</string>
|
||||
<string name="firmware_uninstalled_success">فرمور با موفقیت حذف شد</string>
|
||||
|
||||
<string name="provoking_vertex">رأس تحریککننده</string>
|
||||
<string name="provoking_vertex_description">نورپردازی و مدیریت رأس را در برخی بازیها بهبود میبخشد. فقط در کارتهای گرافیک با پشتیبانی از ولکان 1.0+ قابل استفاده است</string>
|
||||
<string name="descriptor_indexing">نمایهسازی توصیفگر</string>
|
||||
<string name="descriptor_indexing_description">مدیریت بافتها و بافرها و همچنین لایه ترجمه ماکسول را بهبود میبخشد. توسط برخی کارتهای گرافیک ولکان 1.1 و تمام کارتهای گرافیک ولکان 1.2+ پشتیبانی میشود</string>
|
||||
<string name="fast_gpu_time">فاکتور اورکلاک GPU</string>
|
||||
<string name="fast_gpu_time_description">برای حداکثر عملکرد از 128 و برای حداکثر وفاداری گرافیکی از 512 استفاده کنید.</string>
|
||||
<string name="fast_gpu_medium">متوسط (256)</string>
|
||||
|
||||
@@ -441,7 +441,10 @@
|
||||
<string name="disabled">Désactivé</string>
|
||||
<string name="vertex_input_dynamic_state">État dynamique d\'entrée de sommet</string>
|
||||
<string name="vertex_input_dynamic_state_description">Active la fonctionnalité d\'état dynamique des entrées de sommets pour une meilleure qualité et de meilleures performances.</string>
|
||||
|
||||
<string name="provoking_vertex">Provoque des Vertex</string>
|
||||
<string name="provoking_vertex_description">Améliore l`éclairage et la gestion des vertex dans certains jeux. Pris en charge uniquement par les GPU Vulkan 1.0+.</string>
|
||||
<string name="descriptor_indexing">Indexation des descripteurs</string>
|
||||
<string name="descriptor_indexing_description">Améliore la gestion des textures et des tampons, ainsi que la couche de traduction Maxwell. Pris en charge par certains GPU Vulkan 1.1 et tous les GPU Vulkan 1.2+.</string>
|
||||
<string name="display">Affichage</string>
|
||||
|
||||
<string name="renderer_screen_layout">Orientation</string>
|
||||
|
||||
@@ -399,7 +399,10 @@
|
||||
<string name="renderer_asynchronous_shaders_description">מקמפל שיידרים באופן אסינכרוני. זה עשוי להפחית קפיצות אך גם עלול לגרום לתקלות גרפיות.</string>
|
||||
<string name="dyna_state">מצב דינמי מורחב</string>
|
||||
<string name="disabled">מושבת</string>
|
||||
|
||||
<string name="provoking_vertex">קודקוד מעורר</string>
|
||||
<string name="provoking_vertex_description">משפר תאורה וטיפול בקודקודים במשחקים מסוימים. נתמך רק בכרטיסי מסך עם Vulkan 1.0+.</string>
|
||||
<string name="descriptor_indexing">אינדוקס תיאורים</string>
|
||||
<string name="descriptor_indexing_description">משפר טיפול במרקמים ומאגרים, כמו גם בשכבת התרגום של Maxwell. נתמך בחלק מכרטיסי ה-Vulkan 1.1 ובכל כרטיסי ה-Vulkan 1.2+.</string>
|
||||
<string name="display">תצוגה</string>
|
||||
|
||||
<string name="renderer_screen_layout">כיוון</string>
|
||||
|
||||
@@ -387,8 +387,10 @@
|
||||
<string name="renderer_asynchronous_shaders_description">A shaderek aszinkron fordítása. Csökkentheti a belassulásokat, de hibákat is okozhat.</string>
|
||||
<string name="dyna_state">Kiterjesztett Dinamikus Állapot</string>
|
||||
<string name="disabled">Letiltva</string>
|
||||
|
||||
|
||||
<string name="provoking_vertex">Provokáló csúcs</string>
|
||||
<string name="provoking_vertex_description">Javítja a világítást és a csúcskezelést bizonyos játékokban. Csak Vulkan 1.0+ GPU-kon támogatott.</string>
|
||||
<string name="descriptor_indexing">Deskriptor Indexelés</string>
|
||||
<string name="descriptor_indexing_description">Javítja a textúrák és pufferek kezelését, valamint a Maxwell fordítási réteget. Néhány Vulkan 1.1 GPU és minden Vulkan 1.2+ GPU támogatja.</string>
|
||||
<string name="display">Kijelző</string>
|
||||
|
||||
<string name="renderer_screen_layout">Orientáció</string>
|
||||
|
||||
@@ -419,7 +419,10 @@
|
||||
<string name="renderer_asynchronous_shaders_description">Kompilasi shader secara asinkron. Ini dapat mengurangi lag tetapi juga dapat menyebabkan glitch.</string>
|
||||
<string name="dyna_state">Status Dinamis Ekstensi</string>
|
||||
<string name="disabled">Dinonaktifkan</string>
|
||||
|
||||
<string name="provoking_vertex">Vertex Provokasi</string>
|
||||
<string name="provoking_vertex_description">Meningkatkan pencahayaan dan penanganan vertex di beberapa game. Hanya didukung di GPU Vulkan 1.0+.</string>
|
||||
<string name="descriptor_indexing">Pengindeks Deskriptor</string>
|
||||
<string name="descriptor_indexing_description">Meningkatkan penanganan tekstur dan buffer, serta lapisan terjemahan Maxwell. Didukung oleh beberapa GPU Vulkan 1.1 dan semua GPU Vulkan 1.2+.</string>
|
||||
<string name="display">Tampilan</string>
|
||||
|
||||
<string name="renderer_screen_layout">Orientasi</string>
|
||||
|
||||
@@ -426,7 +426,10 @@
|
||||
<string name="renderer_asynchronous_shaders_description">Compila gli shader in modo asincrono. Può ridurre gli scatti, ma può anche causare glitch grafici.</string>
|
||||
<string name="dyna_state">Stato dinamico esteso</string>
|
||||
<string name="disabled">Disabilitato</string>
|
||||
|
||||
<string name="provoking_vertex">Vertice provocante</string>
|
||||
<string name="provoking_vertex_description">Migliora illuminazione e gestione dei vertici in alcuni giochi. Supportato solo su GPU Vulkan 1.0+.</string>
|
||||
<string name="descriptor_indexing">Indicizzazione descrittori</string>
|
||||
<string name="descriptor_indexing_description">Migliora la gestione di texture e buffer, nonché il livello di traduzione Maxwell. Supportato da alcune GPU Vulkan 1.1 e tutte le GPU Vulkan 1.2+.</string>
|
||||
<string name="display">Schermo</string>
|
||||
|
||||
<string name="renderer_screen_layout">Orientamento</string>
|
||||
|
||||
@@ -385,7 +385,10 @@
|
||||
<string name="renderer_asynchronous_shaders_description">シェーダーを非同期でコンパイルします。これによりカクつきが減る可能性がありますが、グラフィックの不具合が発生する場合もあります。</string>
|
||||
<string name="dyna_state">拡張ダイナミックステート</string>
|
||||
<string name="disabled">無効</string>
|
||||
|
||||
<string name="provoking_vertex">プロボーキング頂点</string>
|
||||
<string name="provoking_vertex_description">特定のゲームで照明と頂点処理を改善します。Vulkan 1.0+ GPUでのみサポートされています。</string>
|
||||
<string name="descriptor_indexing">ディスクリプタインデキシング</string>
|
||||
<string name="descriptor_indexing_description">テクスチャとバッファの処理、およびMaxwell翻訳レイヤーを改善します。一部のVulkan 1.1 GPUとすべてのVulkan 1.2+ GPUでサポートされています。</string>
|
||||
<string name="display">ディスプレイ</string>
|
||||
|
||||
<string name="renderer_screen_layout">画面の向き</string>
|
||||
|
||||
@@ -385,7 +385,10 @@
|
||||
<string name="renderer_asynchronous_shaders_description">셰이더를 비동기적으로 컴파일합니다. 이로 인해 끊김 현상이 줄어들 수 있지만 그래픽 오류가 발생할 수도 있습니다.</string>
|
||||
<string name="dyna_state">확장 동적 상태</string>
|
||||
<string name="disabled">비활성화됨</string>
|
||||
|
||||
<string name="provoking_vertex">프로보킹 버텍스</string>
|
||||
<string name="provoking_vertex_description">일부 게임에서 조명과 버텍스 처리를 개선합니다. Vulkan 1.0+ GPU에서만 지원됩니다.</string>
|
||||
<string name="descriptor_indexing">디스크립터 인덱싱</string>
|
||||
<string name="descriptor_indexing_description">텍스처 및 버퍼 처리와 Maxwell 변환 레이어를 개선합니다. 일부 Vulkan 1.1 GPU 및 모든 Vulkan 1.2+ GPU에서 지원됩니다.</string>
|
||||
<string name="display">디스플레이</string>
|
||||
|
||||
<string name="renderer_screen_layout">화면 방향</string>
|
||||
|
||||
@@ -368,7 +368,10 @@
|
||||
<string name="renderer_asynchronous_shaders_description">Kompilerer shadere asynkront. Dette kan redusere rykk, men kan også forårsake grafiske feil.</string>
|
||||
<string name="dyna_state">Utvidet dynamisk tilstand</string>
|
||||
<string name="disabled">Deaktivert</string>
|
||||
|
||||
<string name="provoking_vertex">Provoserende vertex</string>
|
||||
<string name="provoking_vertex_description">Forbedrer belysning og vertexhåndtering i enkelte spill. Støttes kun på Vulkan 1.0+ GPU-er.</string>
|
||||
<string name="descriptor_indexing">Beskrivelsesindeksering</string>
|
||||
<string name="descriptor_indexing_description">Forbedrer tekstur- og bufferhåndtering, samt Maxwell-oversettelseslaget. Støttes av noen Vulkan 1.1 GPU-er og alle Vulkan 1.2+ GPU-er.</string>
|
||||
<string name="display">Skjerm</string>
|
||||
|
||||
<string name="renderer_screen_layout">Orientering</string>
|
||||
|
||||
@@ -493,7 +493,10 @@
|
||||
<string name="disabled">Wyłączone</string>
|
||||
<string name="vertex_input_dynamic_state">Dynamiczny stan wejścia wierzchołków</string>
|
||||
<string name="vertex_input_dynamic_state_description">Włącza funkcję dynamicznego stanu wejścia wierzchołków, poprawiając jakość i wydajność.</string>
|
||||
|
||||
<string name="provoking_vertex">Wierzchołek prowokujący</string>
|
||||
<string name="provoking_vertex_description">Poprawia oświetlenie i obsługę wierzchołków w niektórych grach. Obsługiwane tylko przez GPU Vulkan 1.0+.</string>
|
||||
<string name="descriptor_indexing">Indeksowanie deskryptorów</string>
|
||||
<string name="descriptor_indexing_description">Poprawia obsługę tekstur i buforów oraz warstwę tłumaczenia Maxwell. Obsługiwane przez niektóre GPU Vulkan 1.1 i wszystkie GPU Vulkan 1.2+.</string>
|
||||
<string name="sample_shading_fraction">Cieniowanie próbkowane</string>
|
||||
<string name="sample_shading_fraction_description">Pozwala uruchamiać shader fragmentów dla każdej próbki w wielopróbkowanym fragmencie zamiast raz na fragment. Poprawia jakość grafiki kosztem części wydajności.</string>
|
||||
|
||||
|
||||
@@ -476,7 +476,10 @@
|
||||
<string name="disabled">Desativado</string>
|
||||
<string name="vertex_input_dynamic_state">Vertex Input Dynamic State</string>
|
||||
<string name="vertex_input_dynamic_state_description">Ativa o recurso de vertex input dynamic state para melhor qualidade e desempenho.</string>
|
||||
|
||||
<string name="provoking_vertex">Provoking Vertex</string>
|
||||
<string name="provoking_vertex_description">Vértice Provocante: Melhora a iluminação e o processamento de vértices em certos jogos. Suportado apenas em GPUs com Vulkan 1.0 ou superior.</string>
|
||||
<string name="descriptor_indexing">Descriptor Indexing</string>
|
||||
<string name="descriptor_indexing_description">Indexação de Descritores: Melhora o processamento de texturas e buffers, assim como a camada de tradução Maxwell. Suportado por algumas GPUs Vulkan 1.1 e todas as GPUs Vulkan 1.2 ou superiores.</string>
|
||||
<string name="display">Tela</string>
|
||||
|
||||
<string name="renderer_screen_layout">Orientação</string>
|
||||
|
||||
@@ -391,7 +391,10 @@
|
||||
<string name="renderer_asynchronous_shaders_description">Compila shaders de forma assíncrona. Isto pode reduzir engasgadelas, mas também pode introduzir falhas gráficas.</string>
|
||||
<string name="dyna_state">Estado Dinâmico Estendido</string>
|
||||
<string name="disabled">Desativado</string>
|
||||
|
||||
<string name="provoking_vertex">Vértice provocante</string>
|
||||
<string name="provoking_vertex_description">Melhora a iluminação e o tratamento de vértices em certos jogos. Suportado apenas em GPUs Vulkan 1.0+.</string>
|
||||
<string name="descriptor_indexing">Indexação de descritores</string>
|
||||
<string name="descriptor_indexing_description">Melhora o tratamento de texturas e buffers, assim como a camada de tradução Maxwell. Suportado por algumas GPUs Vulkan 1.1 e todas Vulkan 1.2+.</string>
|
||||
<string name="display">Ecrã</string>
|
||||
|
||||
<string name="renderer_screen_layout">Oriantação</string>
|
||||
|
||||
@@ -503,7 +503,10 @@
|
||||
<string name="disabled">Отключено</string>
|
||||
<string name="vertex_input_dynamic_state">Динамическое состояние ввода вершин</string>
|
||||
<string name="vertex_input_dynamic_state_description">Включает функцию динамического состояния ввода вершин для повышения качества и производительности</string>
|
||||
|
||||
<string name="provoking_vertex">Определяющая вершина</string>
|
||||
<string name="provoking_vertex_description">Улучшает освещение и обработку вершин в некоторых играх. Поддерживается только ГПУ с Vulkan 1.0+.</string>
|
||||
<string name="descriptor_indexing">Индексирование дескрипторов</string>
|
||||
<string name="descriptor_indexing_description">Улучшает обработку текстур и буферов, а также слой перевода Maxwell. Поддерживается некоторыми ГПУ Vulkan 1.1 и всеми ГПУ Vulkan 1.2+.</string>
|
||||
<string name="sample_shading_fraction">Сэмпловое затенение</string>
|
||||
<string name="sample_shading_fraction_description">Позволяет шейдеру фрагментов выполняться для каждого сэмпла в многосэмпловом фрагменте, а не один раз на фрагмент. Улучшает качество графики ценой некоторого падения производительности.</string>
|
||||
|
||||
|
||||
@@ -390,7 +390,10 @@
|
||||
<string name="renderer_asynchronous_shaders_description">Саставља схадера асинхроно. Ово може умањити затезаче, али могу такође да уведе пропусте.</string>
|
||||
<string name="dyna_state">Проширена динамичка држава</string>
|
||||
<string name="disabled">Искључено</string>
|
||||
|
||||
<string name="provoking_vertex">Провоцирајући врх</string>
|
||||
<string name="provoking_vertex_description">Побољшава осветљење и вертификат руковања у одређеним играма. Подржан само на Вулкану 1.0+ ГПУ-у.</string>
|
||||
<string name="descriptor_indexing">Индексирање дескриптора</string>
|
||||
<string name="descriptor_indexing_description">Побољшава текстуру и руковање међуспремника, као и преводилачки слој Маквелл. Подржани од стране неких Вулкана 1.1 ГПУ-а и сви Вулкан 1.2+ ГПУ.</string>
|
||||
<string name="display">Приказ</string>
|
||||
|
||||
<string name="renderer_screen_layout">Оријентација</string>
|
||||
|
||||
@@ -507,7 +507,10 @@
|
||||
<string name="disabled">Вимкнено</string>
|
||||
<string name="vertex_input_dynamic_state">Динамічний стан введення вершин</string>
|
||||
<string name="vertex_input_dynamic_state_description">Вмикає можливість динамічного стану введення вершин для кращих якості й продуктивності.</string>
|
||||
|
||||
<string name="provoking_vertex">Провокативна вершина</string>
|
||||
<string name="provoking_vertex_description">Покращує освітлення та взаємодію з вершинами у деяких іграх. Лише для ГП з підтримкою Vulkan 1.0+.</string>
|
||||
<string name="descriptor_indexing">Індексація дескрипторів</string>
|
||||
<string name="descriptor_indexing_description">Покращує обробку текстур та буферів, а також шар перекладу Maxwell. Підтримується деякими GPU Vulkan 1.1 та всіма GPU Vulkan 1.2+.</string>
|
||||
<string name="sample_shading_fraction">Простий шейдинг</string>
|
||||
<string name="sample_shading_fraction_description">Дозволяє виконувати фрагмент шейдера для кожного зразка в багатозразковому фрагменті замість одного разу для кожного фрагмента. Покращує якість графікі ціною втрати продуктивності.</string>
|
||||
|
||||
|
||||
@@ -366,7 +366,10 @@
|
||||
<string name="renderer_asynchronous_shaders_description">Biên dịch shader không đồng bộ. Điều này có thể giảm giật lag nhưng cũng có thể gây ra lỗi đồ họa.</string>
|
||||
<string name="dyna_state">Trạng thái động mở rộng</string>
|
||||
<string name="disabled">Đã tắt</string>
|
||||
|
||||
<string name="provoking_vertex">Đỉnh kích hoạt</string>
|
||||
<string name="provoking_vertex_description">Cải thiện ánh sáng và xử lý đỉnh trong một số trò chơi. Chỉ được hỗ trợ trên GPU Vulkan 1.0+.</string>
|
||||
<string name="descriptor_indexing">Lập chỉ mục bộ mô tả</string>
|
||||
<string name="descriptor_indexing_description">Cải thiện xử lý kết cấu và bộ đệm, cũng như lớp dịch Maxwell. Được hỗ trợ bởi một số GPU Vulkan 1.1 và tất cả GPU Vulkan 1.2+.</string>
|
||||
<string name="display">Hiển thị</string>
|
||||
|
||||
<string name="renderer_screen_layout">Hướng màn hình</string>
|
||||
|
||||
@@ -501,7 +501,10 @@
|
||||
<string name="disabled">已禁用</string>
|
||||
<string name="vertex_input_dynamic_state">顶点输入动态状态</string>
|
||||
<string name="vertex_input_dynamic_state_description">开启顶点输入动态状态功能来获得更好的质量和性能。</string>
|
||||
|
||||
<string name="provoking_vertex">引发顶点</string>
|
||||
<string name="provoking_vertex_description">改善某些游戏中的光照和顶点处理。仅支持Vulkan 1.0+ GPU。</string>
|
||||
<string name="descriptor_indexing">描述符索引</string>
|
||||
<string name="descriptor_indexing_description">改进纹理和缓冲区处理以及Maxwell转换层。部分Vulkan 1.1 GPU和所有Vulkan 1.2+ GPU支持。</string>
|
||||
<string name="sample_shading_fraction">采样着色</string>
|
||||
<string name="sample_shading_fraction_description">允许片段着色器在多采样片段中每个样本执行一次,而不是每个片段执行一次。以提高性能为代价改善图形质量。</string>
|
||||
|
||||
|
||||
@@ -472,7 +472,10 @@
|
||||
<string name="disabled">已停用</string>
|
||||
<string name="vertex_input_dynamic_state">頂點輸入動態狀態</string>
|
||||
<string name="vertex_input_dynamic_state_description">啟用頂點輸入動態狀態以取得更佳的品質及性能</string>
|
||||
|
||||
<string name="provoking_vertex">引發頂點</string>
|
||||
<string name="provoking_vertex_description">改善某些遊戲中的光照和頂點處理。僅支援Vulkan 1.0+ GPU。</string>
|
||||
<string name="descriptor_indexing">描述符索引</string>
|
||||
<string name="descriptor_indexing_description">改進紋理和緩衝區處理以及Maxwell轉換層。部分Vulkan 1.1 GPU和所有Vulkan 1.2+ GPU支援。</string>
|
||||
<string name="display">顯示</string>
|
||||
|
||||
<string name="renderer_screen_layout">方向</string>
|
||||
|
||||
@@ -123,25 +123,13 @@
|
||||
<item>1</item> <!-- Aggressive -->
|
||||
</integer-array>
|
||||
|
||||
<!-- ASTC Decoding Method Choices -->
|
||||
<string-array name="astcDecodingMethodNames">
|
||||
<item>@string/accelerate_astc_cpu</item>
|
||||
<item>@string/accelerate_astc_gpu</item>
|
||||
<item>@string/accelerate_astc_async</item>
|
||||
</string-array>
|
||||
|
||||
<!-- ASTC Decoding Method Values -->
|
||||
<integer-array name="astcDecodingMethodValues">
|
||||
<item>0</item> <!-- CPU -->
|
||||
<item>1</item> <!-- GPU -->
|
||||
<item>2</item> <!-- CPU Asynchronously -->
|
||||
</integer-array>
|
||||
|
||||
<!-- ASTC Recompression Method Choices -->
|
||||
<string-array name="astcRecompressionMethodNames">
|
||||
<item>@string/astc_recompression_uncompressed</item>
|
||||
<item>@string/astc_recompression_bc1</item>
|
||||
<item>@string/astc_recompression_bc3</item>
|
||||
<item>@string/astc_recompression_bc7</item>
|
||||
<item>@string/astc_recompression_etc2</item>
|
||||
</string-array>
|
||||
|
||||
<!-- ASTC Recompression Method Values -->
|
||||
@@ -149,6 +137,8 @@
|
||||
<item>0</item> <!-- Uncompressed -->
|
||||
<item>1</item> <!-- BC1 -->
|
||||
<item>2</item> <!-- BC3 -->
|
||||
<item>3</item> <!-- BC7 -->
|
||||
<item>4</item> <!-- ETC2 -->
|
||||
</integer-array>
|
||||
|
||||
<!-- NVDEC Emulation Choices -->
|
||||
@@ -611,7 +601,7 @@
|
||||
</integer-array>
|
||||
|
||||
<string-array name="dynaStateEntries">
|
||||
<item>Core</item>
|
||||
<item>@string/disabled</item>
|
||||
<item>ExtendedDynamicState 1</item>
|
||||
<item>ExtendedDynamicState 2</item>
|
||||
<item>ExtendedDynamicState 3</item>
|
||||
|
||||
@@ -520,6 +520,10 @@
|
||||
<string name="disabled">Disabled</string>
|
||||
<string name="vertex_input_dynamic_state">Vertex Input Dynamic State</string>
|
||||
<string name="vertex_input_dynamic_state_description">Enables vertex input dynamic state feature for better quality and performance.</string>
|
||||
<string name="provoking_vertex">Provoking Vertex</string>
|
||||
<string name="provoking_vertex_description">Improves lighting and vertex handling in certain games. Only supported on Vulkan 1.0+ GPUs.</string>
|
||||
<string name="descriptor_indexing">Descriptor Indexing</string>
|
||||
<string name="descriptor_indexing_description">Improves texture and buffer handling, as well as the Maxwell translation layer. Supported by some Vulkan 1.1 GPUs and all Vulkan 1.2+ GPUs.</string>
|
||||
<string name="sample_shading_fraction">Sample Shading</string>
|
||||
<string name="sample_shading_fraction_description">Allows the fragment shader to execute per sample in a multi-sampled fragment instead once per fragment. Improves graphics quality at the cost of some performance.</string>
|
||||
|
||||
@@ -1029,6 +1033,8 @@
|
||||
<string name="astc_recompression_uncompressed">Uncompressed</string>
|
||||
<string name="astc_recompression_bc1" translatable="false">BC1</string>
|
||||
<string name="astc_recompression_bc3" translatable="false">BC3</string>
|
||||
<string name="astc_recompression_bc7" translatable="false">BC7</string>
|
||||
<string name="astc_recompression_etc2" translatable="false">ETC2</string>
|
||||
|
||||
<!-- ASTC Recompression Method Choices -->
|
||||
<string name="vram_usage_conservative">Conservative</string>
|
||||
@@ -1159,6 +1165,12 @@
|
||||
<string name="use_black_backgrounds">Black backgrounds</string>
|
||||
<string name="use_black_backgrounds_description">When using the dark theme, apply black backgrounds.</string>
|
||||
|
||||
<!-- Buttons -->
|
||||
<string name="enable_folder_button">Folder</string>
|
||||
<string name="enable_folder_button_description">Show the button to add game folders</string>
|
||||
<string name="enable_qlaunch_button">QLaunch</string>
|
||||
<string name="enable_qlaunch_button_description">Show the button to launch QLaunch</string>
|
||||
|
||||
<!-- App Language -->
|
||||
<string name="app_language">App Language</string>
|
||||
<string name="app_language_description">Change the language of the app interface</string>
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#define BUILD_AUTO_UPDATE_WEBSITE "@BUILD_AUTO_UPDATE_WEBSITE@"
|
||||
#define BUILD_AUTO_UPDATE_API "@BUILD_AUTO_UPDATE_API@"
|
||||
#define BUILD_AUTO_UPDATE_REPO "@BUILD_AUTO_UPDATE_REPO@"
|
||||
#define IS_NIGHTLY_BUILD @IS_NIGHTLY_BUILD@
|
||||
|
||||
namespace Common {
|
||||
|
||||
@@ -35,7 +36,9 @@ constexpr const char g_build_id[] = BUILD_ID;
|
||||
constexpr const char g_title_bar_format_idle[] = TITLE_BAR_FORMAT_IDLE;
|
||||
constexpr const char g_title_bar_format_running[] = TITLE_BAR_FORMAT_RUNNING;
|
||||
constexpr const char g_compiler_id[] = COMPILER_ID;
|
||||
|
||||
constexpr const bool g_is_dev_build = IS_DEV_BUILD;
|
||||
constexpr const bool g_is_nightly_build = IS_NIGHTLY_BUILD;
|
||||
|
||||
constexpr const char g_build_auto_update_website[] = BUILD_AUTO_UPDATE_WEBSITE;
|
||||
constexpr const char g_build_auto_update_api[] = BUILD_AUTO_UPDATE_API;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: 2014 Citra Emulator Project
|
||||
@@ -20,7 +20,10 @@ extern const char g_title_bar_format_idle[];
|
||||
extern const char g_title_bar_format_running[];
|
||||
extern const char g_shader_cache_version[];
|
||||
extern const char g_compiler_id[];
|
||||
|
||||
extern const bool g_is_dev_build;
|
||||
extern const bool g_is_nightly_build;
|
||||
|
||||
extern const char g_build_auto_update_website[];
|
||||
extern const char g_build_auto_update_api[];
|
||||
extern const char g_build_auto_update_repo[];
|
||||
|
||||
+4
-11
@@ -430,15 +430,6 @@ struct Values {
|
||||
#endif
|
||||
"max_anisotropy",
|
||||
Category::RendererAdvanced};
|
||||
SwitchableSetting<AstcDecodeMode, true> accelerate_astc{linkage,
|
||||
#ifdef ANDROID
|
||||
AstcDecodeMode::Cpu,
|
||||
#else
|
||||
AstcDecodeMode::Gpu,
|
||||
#endif
|
||||
"accelerate_astc",
|
||||
Category::RendererAdvanced};
|
||||
|
||||
SwitchableSetting<AstcRecompression, true> astc_recompression{linkage,
|
||||
AstcRecompression::Uncompressed,
|
||||
"astc_recompression",
|
||||
@@ -535,9 +526,9 @@ struct Values {
|
||||
#elif defined (__FreeBSD__)
|
||||
ExtendedDynamicState::EDS3,
|
||||
#elif defined (ANDROID)
|
||||
ExtendedDynamicState::Core,
|
||||
ExtendedDynamicState::Disabled,
|
||||
#elif defined (__APPLE__)
|
||||
ExtendedDynamicState::Core,
|
||||
ExtendedDynamicState::Disabled,
|
||||
#else
|
||||
ExtendedDynamicState::EDS2,
|
||||
#endif
|
||||
@@ -559,6 +550,8 @@ struct Values {
|
||||
true,
|
||||
#endif
|
||||
"vertex_input_dynamic_state", Category::RendererExtensions};
|
||||
SwitchableSetting<bool> provoking_vertex{linkage, false, "provoking_vertex", Category::RendererExtensions};
|
||||
SwitchableSetting<bool> descriptor_indexing{linkage, false, "descriptor_indexing", Category::RendererExtensions};
|
||||
|
||||
Setting<bool> renderer_debug{linkage, false, "debug", Category::RendererDebug};
|
||||
Setting<bool> renderer_shader_feedback{linkage, false, "shader_feedback",
|
||||
|
||||
@@ -128,7 +128,7 @@ ENUM(TimeZone, Auto, Default, Cet, Cst6Cdt, Cuba, Eet, Egypt, Eire, Est, Est5Edt
|
||||
Roc, Rok, Singapore, Turkey, Uct, Universal, Utc, WSu, Wet, Zulu);
|
||||
ENUM(AnisotropyMode, Automatic, Default, X2, X4, X8, X16, X32, X64, None);
|
||||
ENUM(AstcDecodeMode, Cpu, Gpu, CpuAsynchronous);
|
||||
ENUM(AstcRecompression, Uncompressed, Bc1, Bc3);
|
||||
ENUM(AstcRecompression, Uncompressed, Bc1, Bc3, Bc7, Etc2);
|
||||
ENUM(VSyncMode, Immediate, Mailbox, Fifo, FifoRelaxed);
|
||||
ENUM(VramUsageMode, Conservative, Aggressive);
|
||||
ENUM(RendererBackend, OpenGL_GLSL, Vulkan, Null, OpenGL_GLASM, OpenGL_SPIRV);
|
||||
@@ -153,7 +153,7 @@ ENUM(GpuUnswizzleSize, VerySmall, Small, Normal, Large, VeryLarge)
|
||||
ENUM(GpuUnswizzle, VeryLow, Low, Normal, Medium, High)
|
||||
ENUM(GpuUnswizzleChunk, VeryLow, Low, Normal, Medium, High)
|
||||
ENUM(TemperatureUnits, Celsius, Fahrenheit)
|
||||
ENUM(ExtendedDynamicState, Core, EDS1, EDS2, EDS3);
|
||||
ENUM(ExtendedDynamicState, Disabled, EDS1, EDS2, EDS3);
|
||||
ENUM(GpuLogLevel, Off, Errors, Standard, Verbose, All)
|
||||
|
||||
template <typename Type>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||
@@ -144,7 +144,7 @@ FSP_SRV::FSP_SRV(Core::System& system_)
|
||||
{617, nullptr, "UnregisterExternalKey"},
|
||||
{620, nullptr, "SetSdCardEncryptionSeed"},
|
||||
{630, nullptr, "SetSdCardAccessibility"},
|
||||
{631, nullptr, "IsSdCardAccessible"},
|
||||
{631, D<&FSP_SRV::IsSdCardAccessible>, "IsSdCardAccessible"},
|
||||
{640, nullptr, "IsSignedSystemPartitionOnSdCardValid"},
|
||||
{700, nullptr, "OpenAccessFailureResolver"},
|
||||
{701, nullptr, "GetAccessFailureDetectionEvent"},
|
||||
@@ -524,6 +524,14 @@ Result FSP_SRV::OpenDataStorageWithProgramIndex(OutInterface<IStorage> out_inter
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result FSP_SRV::IsSdCardAccessible(Out<bool> out_is_accessible) {
|
||||
LOG_DEBUG(Service_FS, "(STUBBED) called");
|
||||
|
||||
*out_is_accessible = true;
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result FSP_SRV::DisableAutoSaveDataCreation() {
|
||||
LOG_DEBUG(Service_FS, "called");
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||
@@ -101,6 +101,7 @@ private:
|
||||
Result OpenPatchDataStorageByCurrentProcess(OutInterface<IStorage> out_interface,
|
||||
FileSys::StorageId storage_id, u64 title_id);
|
||||
Result OpenDataStorageWithProgramIndex(OutInterface<IStorage> out_interface, u8 program_index);
|
||||
Result IsSdCardAccessible(Out<bool> out_is_accessible);
|
||||
Result DisableAutoSaveDataCreation();
|
||||
Result SetGlobalAccessLogMode(AccessLogMode access_log_mode_);
|
||||
Result GetGlobalAccessLogMode(Out<AccessLogMode> out_access_log_mode);
|
||||
|
||||
@@ -5,10 +5,13 @@
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "update_checker.h"
|
||||
#include <boost/algorithm/string/classification.hpp>
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include "common/logging/log.h"
|
||||
#include "common/scm_rev.h"
|
||||
#include <fmt/format.h>
|
||||
#include "update_checker.h"
|
||||
|
||||
#include <httplib.h>
|
||||
|
||||
@@ -137,3 +140,41 @@ std::optional<UpdateChecker::Update> UpdateChecker::GetLatestRelease(bool includ
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<UpdateChecker::Update> UpdateChecker::GetUpdate() {
|
||||
const bool is_prerelease = ((strstr(Common::g_build_version, "pre-alpha") != NULL) ||
|
||||
(strstr(Common::g_build_version, "alpha") != NULL) ||
|
||||
(strstr(Common::g_build_version, "beta") != NULL) ||
|
||||
(strstr(Common::g_build_version, "rc") != NULL));
|
||||
const std::optional<UpdateChecker::Update> latest_release_tag =
|
||||
UpdateChecker::GetLatestRelease(is_prerelease);
|
||||
|
||||
if (!latest_release_tag)
|
||||
goto empty;
|
||||
|
||||
{
|
||||
std::string tag, build;
|
||||
if (Common::g_is_nightly_build) {
|
||||
std::vector<std::string> result;
|
||||
|
||||
boost::split(result, latest_release_tag->tag, boost::is_any_of("."));
|
||||
if (result.size() != 2)
|
||||
goto empty;
|
||||
tag = result[1];
|
||||
|
||||
boost::split(result, std::string{Common::g_build_version}, boost::is_any_of("-"));
|
||||
if (result.empty())
|
||||
goto empty;
|
||||
build = result[0];
|
||||
} else {
|
||||
tag = latest_release_tag->tag;
|
||||
build = Common::g_build_version;
|
||||
}
|
||||
|
||||
if (tag != build)
|
||||
return latest_release_tag.value();
|
||||
}
|
||||
|
||||
empty:
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
@@ -19,4 +19,5 @@ typedef struct {
|
||||
|
||||
std::optional<std::string> GetResponse(std::string url, std::string path);
|
||||
std::optional<Update> GetLatestRelease(bool include_prereleases);
|
||||
std::optional<Update> GetUpdate();
|
||||
} // namespace UpdateChecker
|
||||
|
||||
@@ -209,14 +209,6 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QObject* parent)
|
||||
tr("Specifies how videos should be decoded.\nIt can either use the CPU or the GPU for "
|
||||
"decoding, or perform no decoding at all (black screen on videos).\n"
|
||||
"In most cases, GPU decoding provides the best performance."));
|
||||
INSERT(Settings,
|
||||
accelerate_astc,
|
||||
tr("ASTC Decoding Method:"),
|
||||
tr("This option controls how ASTC textures should be decoded.\n"
|
||||
"CPU: Use the CPU for decoding.\n"
|
||||
"GPU: Use the GPU's compute shaders to decode ASTC textures (recommended).\n"
|
||||
"CPU Asynchronously: Use the CPU to decode ASTC textures on demand. Eliminates"
|
||||
"ASTC decoding\nstuttering but may present artifacts."));
|
||||
INSERT(
|
||||
Settings,
|
||||
astc_recompression,
|
||||
@@ -345,6 +337,18 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QObject* parent)
|
||||
tr("Vertex Input Dynamic State"),
|
||||
tr("Enables vertex input dynamic state feature for better quality and performance."));
|
||||
|
||||
INSERT(Settings,
|
||||
provoking_vertex,
|
||||
tr("Provoking Vertex"),
|
||||
tr("Improves lighting and vertex handling in some games.\n"
|
||||
"Only Vulkan 1.0+ devices support this extension."));
|
||||
|
||||
INSERT(Settings,
|
||||
descriptor_indexing,
|
||||
tr("Descriptor Indexing"),
|
||||
tr("Improves texture & buffer handling and the Maxwell translation layer.\n"
|
||||
"Some Vulkan 1.1+ and all 1.2+ devices support this extension."));
|
||||
|
||||
INSERT(Settings,
|
||||
sample_shading,
|
||||
tr("Sample Shading"),
|
||||
@@ -478,8 +482,10 @@ std::unique_ptr<ComboboxTranslationMap> ComboboxEnumeration(QObject* parent)
|
||||
{Settings::EnumMetadata<Settings::AstcRecompression>::Index(),
|
||||
{
|
||||
PAIR(AstcRecompression, Uncompressed, tr("Uncompressed (Best quality)")),
|
||||
PAIR(AstcRecompression, Bc1, tr("BC1 (Low quality)")),
|
||||
PAIR(AstcRecompression, Bc3, tr("BC3 (Medium quality)")),
|
||||
PAIR(AstcRecompression, Bc1, tr("BC1")),
|
||||
PAIR(AstcRecompression, Bc3, tr("BC3")),
|
||||
PAIR(AstcRecompression, Bc7, tr("BC7")),
|
||||
PAIR(AstcRecompression, Etc2, tr("ETC2")),
|
||||
}});
|
||||
translations->insert({Settings::EnumMetadata<Settings::VramUsageMode>::Index(),
|
||||
{
|
||||
@@ -744,7 +750,7 @@ std::unique_ptr<ComboboxTranslationMap> ComboboxEnumeration(QObject* parent)
|
||||
|
||||
translations->insert({Settings::EnumMetadata<Settings::ExtendedDynamicState>::Index(),
|
||||
{
|
||||
PAIR(ExtendedDynamicState, Core, tr("Core")),
|
||||
PAIR(ExtendedDynamicState, Disabled, tr("Disabled")),
|
||||
PAIR(ExtendedDynamicState, EDS1, tr("ExtendedDynamicState 1")),
|
||||
PAIR(ExtendedDynamicState, EDS2, tr("ExtendedDynamicState 2")),
|
||||
PAIR(ExtendedDynamicState, EDS3, tr("ExtendedDynamicState 3")),
|
||||
|
||||
@@ -279,8 +279,6 @@ add_library(video_core STATIC
|
||||
texture_cache/types.h
|
||||
texture_cache/util.cpp
|
||||
texture_cache/util.h
|
||||
textures/astc.h
|
||||
textures/astc.cpp
|
||||
textures/bcn.cpp
|
||||
textures/bcn.h
|
||||
textures/decoders.cpp
|
||||
|
||||
@@ -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-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
|
||||
@@ -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-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
// SDPX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -92,7 +89,7 @@ struct CommandDataContainer {
|
||||
|
||||
/// Struct used to synchronize the GPU thread
|
||||
struct SynchState final {
|
||||
using CommandQueue = Common::SPSCQueue<CommandDataContainer>;
|
||||
using CommandQueue = Common::MPSCQueue<CommandDataContainer>;
|
||||
std::mutex write_lock;
|
||||
CommandQueue queue;
|
||||
u64 last_fence{};
|
||||
|
||||
@@ -90,7 +90,7 @@ if ("${GLSLANGVALIDATOR}" STREQUAL "GLSLANGVALIDATOR-NOTFOUND")
|
||||
message(FATAL_ERROR "Required program `glslangValidator` not found.")
|
||||
endif()
|
||||
|
||||
set(GLSL_FLAGS "")
|
||||
set(GLSL_FLAGS "-Os")
|
||||
set(SPIR_V_VERSION "spirv1.3")
|
||||
set(QUIET_FLAG "--quiet")
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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-FileCopyrightText: 2015 Citra Emulator Project
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
||||
@@ -235,9 +235,7 @@ void ApplySwizzle(GLuint handle, PixelFormat format, std::array<SwizzleSource, 4
|
||||
[[nodiscard]] bool CanBeAccelerated(const TextureCacheRuntime& runtime,
|
||||
const VideoCommon::ImageInfo& info) {
|
||||
if (IsPixelFormatASTC(info.format) && info.size.depth == 1 && !runtime.HasNativeASTC()) {
|
||||
return Settings::values.accelerate_astc.GetValue() == Settings::AstcDecodeMode::Gpu &&
|
||||
Settings::values.astc_recompression.GetValue() ==
|
||||
Settings::AstcRecompression::Uncompressed;
|
||||
return true;
|
||||
}
|
||||
// Disable other accelerated uploads for now as they don't implement swizzled uploads
|
||||
return false;
|
||||
@@ -266,15 +264,6 @@ void ApplySwizzle(GLuint handle, PixelFormat format, std::array<SwizzleSource, 4
|
||||
return format_info.compatibility_class == store_class;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool CanBeDecodedAsync(const TextureCacheRuntime& runtime,
|
||||
const VideoCommon::ImageInfo& info) {
|
||||
if (IsPixelFormatASTC(info.format) && !runtime.HasNativeASTC()) {
|
||||
return Settings::values.accelerate_astc.GetValue() ==
|
||||
Settings::AstcDecodeMode::CpuAsynchronous;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
[[nodiscard]] CopyOrigin MakeCopyOrigin(VideoCommon::Offset3D offset,
|
||||
VideoCommon::SubresourceLayers subresource, GLenum target) {
|
||||
switch (target) {
|
||||
@@ -443,18 +432,15 @@ OGLTexture MakeImage(const VideoCommon::ImageInfo& info, GLenum gl_internal_form
|
||||
}
|
||||
|
||||
[[nodiscard]] bool IsAstcRecompressionEnabled() {
|
||||
return Settings::values.astc_recompression.GetValue() !=
|
||||
Settings::AstcRecompression::Uncompressed;
|
||||
return Settings::values.astc_recompression.GetValue() != Settings::AstcRecompression::Uncompressed;
|
||||
}
|
||||
|
||||
[[nodiscard]] GLenum SelectAstcFormat(PixelFormat format, bool is_srgb) {
|
||||
switch (Settings::values.astc_recompression.GetValue()) {
|
||||
case Settings::AstcRecompression::Bc1:
|
||||
return is_srgb ? GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT : GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
|
||||
break;
|
||||
case Settings::AstcRecompression::Bc3:
|
||||
return is_srgb ? GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT : GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
||||
break;
|
||||
default:
|
||||
return is_srgb ? GL_SRGB8_ALPHA8 : GL_RGBA8;
|
||||
}
|
||||
@@ -693,12 +679,9 @@ bool TextureCacheRuntime::HasNativeASTC() const noexcept {
|
||||
return device.HasASTC();
|
||||
}
|
||||
|
||||
Image::Image(TextureCacheRuntime& runtime_, const VideoCommon::ImageInfo& info_, GPUVAddr gpu_addr_,
|
||||
VAddr cpu_addr_)
|
||||
Image::Image(TextureCacheRuntime& runtime_, const VideoCommon::ImageInfo& info_, GPUVAddr gpu_addr_, VAddr cpu_addr_)
|
||||
: VideoCommon::ImageBase(info_, gpu_addr_, cpu_addr_), runtime{&runtime_} {
|
||||
if (CanBeDecodedAsync(*runtime, info)) {
|
||||
flags |= ImageFlagBits::AsynchronousDecode;
|
||||
} else if (CanBeAccelerated(*runtime, info)) {
|
||||
if (CanBeAccelerated(*runtime, info)) {
|
||||
flags |= ImageFlagBits::AcceleratedUpload;
|
||||
}
|
||||
if (IsConverted(runtime->device, info.format, info.type)) {
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -25,14 +28,11 @@
|
||||
#include "video_core/texture_cache/accelerated_swizzle.h"
|
||||
#include "video_core/texture_cache/types.h"
|
||||
#include "video_core/texture_cache/util.h"
|
||||
#include "video_core/textures/astc.h"
|
||||
#include "video_core/textures/decoders.h"
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
using namespace HostShaders;
|
||||
using namespace Tegra::Texture::ASTC;
|
||||
|
||||
using VideoCommon::Extent2D;
|
||||
using VideoCommon::Extent3D;
|
||||
using VideoCommon::ImageCopy;
|
||||
@@ -141,10 +141,8 @@ void UtilShaders::BlockLinearUpload2D(Image& image, const StagingBufferMap& map,
|
||||
glUniform1ui(5, params.x_shift);
|
||||
glUniform1ui(6, params.block_height);
|
||||
glUniform1ui(7, params.block_height_mask);
|
||||
glBindBufferRange(GL_SHADER_STORAGE_BUFFER, BINDING_INPUT_BUFFER, map.buffer, input_offset,
|
||||
image.guest_size_bytes - swizzle.buffer_offset);
|
||||
glBindImageTexture(BINDING_OUTPUT_IMAGE, image.StorageHandle(), swizzle.level, GL_TRUE, 0,
|
||||
GL_WRITE_ONLY, store_format);
|
||||
glBindBufferRange(GL_SHADER_STORAGE_BUFFER, BINDING_INPUT_BUFFER, map.buffer, input_offset, image.guest_size_bytes - swizzle.buffer_offset);
|
||||
glBindImageTexture(BINDING_OUTPUT_IMAGE, image.StorageHandle(), swizzle.level, GL_TRUE, 0, GL_WRITE_ONLY, store_format);
|
||||
glDispatchCompute(num_dispatches_x, num_dispatches_y, image.info.resources.layers);
|
||||
}
|
||||
program_manager.RestoreGuestCompute();
|
||||
|
||||
@@ -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-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
||||
@@ -57,7 +57,6 @@ void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d, DynamicFe
|
||||
const auto topology_ = maxwell3d.draw_manager->GetDrawState().topology;
|
||||
|
||||
raw1 = 0;
|
||||
dynamic_state_enabled.Assign(features.has_dynamic_state ? 1 : 0);
|
||||
extended_dynamic_state.Assign(features.has_extended_dynamic_state ? 1 : 0);
|
||||
extended_dynamic_state_2.Assign(features.has_extended_dynamic_state_2 ? 1 : 0);
|
||||
extended_dynamic_state_2_logic_op.Assign(features.has_extended_dynamic_state_2_logic_op ? 1 : 0);
|
||||
@@ -84,6 +83,7 @@ void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d, DynamicFe
|
||||
depth_enabled.Assign(regs.zeta_enable != 0 ? 1 : 0);
|
||||
depth_format.Assign(static_cast<u32>(regs.zeta.format));
|
||||
y_negate.Assign(regs.window_origin.mode != Maxwell::WindowOrigin::Mode::UpperLeft ? 1 : 0);
|
||||
provoking_vertex_last.Assign(regs.provoking_vertex == Maxwell::ProvokingVertex::Last ? 1 : 0);
|
||||
conservative_raster_enable.Assign(regs.conservative_raster_enable != 0 ? 1 : 0);
|
||||
smooth_lines.Assign(regs.line_anti_alias_enable != 0 ? 1 : 0);
|
||||
alpha_to_coverage_enabled.Assign(regs.anti_alias_alpha_control.alpha_to_coverage != 0 ? 1 : 0);
|
||||
|
||||
@@ -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-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
||||
@@ -21,7 +21,6 @@ namespace Vulkan {
|
||||
using Maxwell = Tegra::Engines::Maxwell3D::Regs;
|
||||
|
||||
struct DynamicFeatures {
|
||||
bool has_dynamic_state;
|
||||
bool has_extended_dynamic_state;
|
||||
bool has_extended_dynamic_state_2;
|
||||
bool has_extended_dynamic_state_2_logic_op;
|
||||
@@ -189,20 +188,19 @@ struct FixedPipelineState {
|
||||
|
||||
union {
|
||||
u32 raw1;
|
||||
BitField<0, 1, u32> dynamic_state_enabled;
|
||||
BitField<1, 1, u32> extended_dynamic_state;
|
||||
BitField<2, 1, u32> extended_dynamic_state_2;
|
||||
BitField<3, 1, u32> extended_dynamic_state_2_logic_op;
|
||||
BitField<4, 1, u32> extended_dynamic_state_3_blend;
|
||||
BitField<5, 1, u32> extended_dynamic_state_3_enables;
|
||||
BitField<6, 1, u32> dynamic_vertex_input;
|
||||
BitField<7, 1, u32> xfb_enabled;
|
||||
BitField<8, 1, u32> ndc_minus_one_to_one;
|
||||
BitField<9, 2, u32> polygon_mode;
|
||||
BitField<11, 2, u32> tessellation_primitive;
|
||||
BitField<13, 2, u32> tessellation_spacing;
|
||||
BitField<15, 1, u32> tessellation_clockwise;
|
||||
BitField<16, 5, u32> patch_control_points_minus_one;
|
||||
BitField<0, 1, u32> extended_dynamic_state;
|
||||
BitField<1, 1, u32> extended_dynamic_state_2;
|
||||
BitField<2, 1, u32> extended_dynamic_state_2_logic_op;
|
||||
BitField<3, 1, u32> extended_dynamic_state_3_blend;
|
||||
BitField<4, 1, u32> extended_dynamic_state_3_enables;
|
||||
BitField<5, 1, u32> dynamic_vertex_input;
|
||||
BitField<6, 1, u32> xfb_enabled;
|
||||
BitField<7, 1, u32> ndc_minus_one_to_one;
|
||||
BitField<8, 2, u32> polygon_mode;
|
||||
BitField<10, 2, u32> tessellation_primitive;
|
||||
BitField<12, 2, u32> tessellation_spacing;
|
||||
BitField<14, 1, u32> tessellation_clockwise;
|
||||
BitField<15, 5, u32> patch_control_points_minus_one;
|
||||
|
||||
BitField<24, 4, Maxwell::PrimitiveTopology> topology;
|
||||
BitField<28, 4, Tegra::Texture::MsaaMode> msaa_mode;
|
||||
@@ -214,8 +212,9 @@ struct FixedPipelineState {
|
||||
BitField<5, 1, u32> depth_enabled;
|
||||
BitField<6, 5, u32> depth_format;
|
||||
BitField<11, 1, u32> y_negate;
|
||||
BitField<12, 1, u32> conservative_raster_enable;
|
||||
BitField<13, 1, u32> smooth_lines;
|
||||
BitField<12, 1, u32> provoking_vertex_last;
|
||||
BitField<13, 1, u32> conservative_raster_enable;
|
||||
BitField<14, 1, u32> smooth_lines;
|
||||
BitField<15, 1, u32> alpha_to_coverage_enabled;
|
||||
BitField<16, 1, u32> alpha_to_one_enabled;
|
||||
BitField<17, 3, Tegra::Engines::Maxwell3D::EngineHint> app_stage;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
||||
@@ -251,6 +251,12 @@ FormatInfo SurfaceFormat(const Device& device, FormatType format_type, bool with
|
||||
case Settings::AstcRecompression::Bc3:
|
||||
tuple.format = is_srgb ? VK_FORMAT_BC3_SRGB_BLOCK : VK_FORMAT_BC3_UNORM_BLOCK;
|
||||
break;
|
||||
case Settings::AstcRecompression::Bc7:
|
||||
tuple.format = is_srgb ? VK_FORMAT_BC7_SRGB_BLOCK : VK_FORMAT_BC7_UNORM_BLOCK;
|
||||
break;
|
||||
case Settings::AstcRecompression::Etc2:
|
||||
tuple.format = is_srgb ? VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK : VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Transcode on hardware that doesn't support BCn natively
|
||||
|
||||
@@ -555,8 +555,7 @@ void BufferCacheRuntime::BindVertexBuffer(u32 index, VkBuffer buffer, u32 offset
|
||||
if (index >= device.GetMaxVertexInputBindings()) {
|
||||
return;
|
||||
}
|
||||
const bool use_stride_dynamic = use_dynamic_vertex_binding_stride;
|
||||
if (use_stride_dynamic) {
|
||||
if (device.IsExtExtendedDynamicStateSupported()) {
|
||||
scheduler.Record([index, buffer, offset, size, stride](vk::CommandBuffer cmdbuf) {
|
||||
const VkDeviceSize vk_offset = buffer != VK_NULL_HANDLE ? offset : 0;
|
||||
const VkDeviceSize vk_size = buffer != VK_NULL_HANDLE ? size : VK_WHOLE_SIZE;
|
||||
@@ -596,8 +595,7 @@ void BufferCacheRuntime::BindVertexBuffers(VideoCommon::HostBindings<Buffer>& bi
|
||||
if (binding_count == 0) {
|
||||
return;
|
||||
}
|
||||
const bool use_stride_dynamic = use_dynamic_vertex_binding_stride;
|
||||
if (use_stride_dynamic) {
|
||||
if (device.IsExtExtendedDynamicStateSupported()) {
|
||||
scheduler.Record([bindings_ = std::move(bindings),
|
||||
buffer_handles_ = std::move(buffer_handles),
|
||||
binding_count](vk::CommandBuffer cmdbuf) {
|
||||
|
||||
@@ -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-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
||||
@@ -127,10 +127,6 @@ public:
|
||||
|
||||
void BindVertexBuffers(VideoCommon::HostBindings<Buffer>& bindings);
|
||||
|
||||
void SetUseDynamicVertexBindingStride(bool enabled) noexcept {
|
||||
use_dynamic_vertex_binding_stride = enabled;
|
||||
}
|
||||
|
||||
void BindTransformFeedbackBuffer(u32 index, VkBuffer buffer, u32 offset, u32 size);
|
||||
|
||||
void BindTransformFeedbackBuffers(VideoCommon::HostBindings<Buffer>& bindings);
|
||||
@@ -189,7 +185,6 @@ private:
|
||||
|
||||
bool limit_dynamic_storage_buffers = false;
|
||||
u32 max_dynamic_storage_buffers = (std::numeric_limits<u32>::max)();
|
||||
bool use_dynamic_vertex_binding_stride = false;
|
||||
};
|
||||
|
||||
struct BufferCacheParams {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
||||
@@ -538,16 +538,16 @@ ASTCDecoderPass::ASTCDecoderPass(const Device& device_, Scheduler& scheduler_,
|
||||
ComputePassDescriptorQueue& compute_pass_descriptor_queue_,
|
||||
MemoryAllocator& memory_allocator_)
|
||||
: ComputePass(device_, descriptor_pool_, ASTC_DESCRIPTOR_SET_BINDINGS,
|
||||
ASTC_PASS_DESCRIPTOR_UPDATE_TEMPLATE_ENTRY, ASTC_BANK_INFO,
|
||||
COMPUTE_PUSH_CONSTANT_RANGE<sizeof(AstcPushConstants)>, ASTC_DECODER_COMP_SPV),
|
||||
scheduler{scheduler_}, staging_buffer_pool{staging_buffer_pool_},
|
||||
compute_pass_descriptor_queue{compute_pass_descriptor_queue_}, memory_allocator{
|
||||
memory_allocator_} {}
|
||||
ASTC_PASS_DESCRIPTOR_UPDATE_TEMPLATE_ENTRY, ASTC_BANK_INFO,
|
||||
COMPUTE_PUSH_CONSTANT_RANGE<sizeof(AstcPushConstants)>, ASTC_DECODER_COMP_SPV)
|
||||
, scheduler{scheduler_}, staging_buffer_pool{staging_buffer_pool_}
|
||||
, compute_pass_descriptor_queue{compute_pass_descriptor_queue_}, memory_allocator{memory_allocator_}
|
||||
{}
|
||||
|
||||
ASTCDecoderPass::~ASTCDecoderPass() = default;
|
||||
|
||||
void ASTCDecoderPass::Assemble(Image& image, const StagingBufferRef& map,
|
||||
std::span<const VideoCommon::SwizzleParameters> swizzles) {
|
||||
void ASTCDecoderPass::Assemble(Image& image, const StagingBufferRef& map, std::span<const VideoCommon::SwizzleParameters> swizzles) {
|
||||
ASSERT(image.info.size.depth == 1);
|
||||
using namespace VideoCommon::Accelerated;
|
||||
const std::array<u32, 2> block_dims{
|
||||
VideoCore::Surface::DefaultBlockWidth(image.info.format),
|
||||
@@ -558,13 +558,11 @@ void ASTCDecoderPass::Assemble(Image& image, const StagingBufferRef& map,
|
||||
const VkImageAspectFlags aspect_mask = image.AspectMask();
|
||||
const VkImage vk_image = image.Handle();
|
||||
const bool is_initialized = image.ExchangeInitialization();
|
||||
scheduler.Record([vk_pipeline, vk_image, aspect_mask,
|
||||
is_initialized](vk::CommandBuffer cmdbuf) {
|
||||
scheduler.Record([vk_pipeline, vk_image, aspect_mask, is_initialized](vk::CommandBuffer cmdbuf) {
|
||||
const VkImageMemoryBarrier image_barrier{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
.pNext = nullptr,
|
||||
.srcAccessMask = static_cast<VkAccessFlags>(is_initialized ? VK_ACCESS_SHADER_WRITE_BIT
|
||||
: VK_ACCESS_NONE),
|
||||
.srcAccessMask = VkAccessFlags(is_initialized ? VK_ACCESS_SHADER_WRITE_BIT : VK_ACCESS_NONE),
|
||||
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
|
||||
.oldLayout = is_initialized ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||
@@ -579,9 +577,7 @@ void ASTCDecoderPass::Assemble(Image& image, const StagingBufferRef& map,
|
||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||
},
|
||||
};
|
||||
cmdbuf.PipelineBarrier(is_initialized ? VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
|
||||
: VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
||||
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, image_barrier);
|
||||
cmdbuf.PipelineBarrier(is_initialized ? VK_PIPELINE_STAGE_ALL_COMMANDS_BIT : VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, image_barrier);
|
||||
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, vk_pipeline);
|
||||
});
|
||||
for (const VideoCommon::SwizzleParameters& swizzle : swizzles) {
|
||||
@@ -591,8 +587,7 @@ void ASTCDecoderPass::Assemble(Image& image, const StagingBufferRef& map,
|
||||
const u32 num_dispatches_z = image.info.resources.layers;
|
||||
|
||||
compute_pass_descriptor_queue.Acquire();
|
||||
compute_pass_descriptor_queue.AddBuffer(map.buffer, input_offset,
|
||||
image.guest_size_bytes - swizzle.buffer_offset);
|
||||
compute_pass_descriptor_queue.AddBuffer(map.buffer, input_offset, image.guest_size_bytes - swizzle.buffer_offset);
|
||||
compute_pass_descriptor_queue.AddImage(image.StorageImageView(swizzle.level));
|
||||
const void* const descriptor_data{compute_pass_descriptor_queue.UpdateData()};
|
||||
|
||||
@@ -601,8 +596,7 @@ void ASTCDecoderPass::Assemble(Image& image, const StagingBufferRef& map,
|
||||
ASSERT(params.origin == (std::array<u32, 3>{0, 0, 0}));
|
||||
ASSERT(params.destination == (std::array<s32, 3>{0, 0, 0}));
|
||||
ASSERT(params.bytes_per_block_log2 == 4);
|
||||
scheduler.Record([this, num_dispatches_x, num_dispatches_y, num_dispatches_z, block_dims,
|
||||
params, descriptor_data](vk::CommandBuffer cmdbuf) {
|
||||
scheduler.Record([this, num_dispatches_x, num_dispatches_y, num_dispatches_z, block_dims, params, descriptor_data](vk::CommandBuffer cmdbuf) {
|
||||
const AstcPushConstants uniforms{
|
||||
.blocks_dims = block_dims,
|
||||
.layer_stride = params.layer_stride,
|
||||
@@ -637,8 +631,7 @@ void ASTCDecoderPass::Assemble(Image& image, const StagingBufferRef& map,
|
||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||
},
|
||||
};
|
||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, image_barrier);
|
||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, image_barrier);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -462,6 +462,7 @@ bool GraphicsPipeline::ConfigureImpl(bool is_indexed) {
|
||||
}
|
||||
|
||||
buffer_cache.UpdateGraphicsBuffers(is_indexed);
|
||||
buffer_cache.BindHostGeometryBuffers(is_indexed);
|
||||
|
||||
guest_descriptor_queue.Acquire();
|
||||
|
||||
@@ -499,8 +500,6 @@ bool GraphicsPipeline::ConfigureImpl(bool is_indexed) {
|
||||
texture_cache.CheckFeedbackLoop(views);
|
||||
ConfigureDraw(rescaling, render_area);
|
||||
|
||||
buffer_cache.BindHostGeometryBuffers(is_indexed);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -742,7 +741,9 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
|
||||
VkPipelineRasterizationProvokingVertexStateCreateInfoEXT provoking_vertex{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT,
|
||||
.pNext = nullptr,
|
||||
.provokingVertexMode = VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT,
|
||||
.provokingVertexMode = key.state.provoking_vertex_last != 0
|
||||
? VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT
|
||||
: VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT,
|
||||
};
|
||||
|
||||
if (IsLine(input_assembly_topology) && device.IsExtLineRasterizationSupported()) {
|
||||
@@ -751,7 +752,7 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
|
||||
if (device.IsExtConservativeRasterizationSupported()) {
|
||||
conservative_raster.pNext = std::exchange(rasterization_ci.pNext, &conservative_raster);
|
||||
}
|
||||
if (device.IsExtProvokingVertexSupported()) {
|
||||
if (device.IsExtProvokingVertexSupported() && Settings::values.provoking_vertex.GetValue()) {
|
||||
provoking_vertex.pNext = std::exchange(rasterization_ci.pNext, &provoking_vertex);
|
||||
}
|
||||
|
||||
@@ -825,22 +826,13 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
|
||||
.pAttachments = cb_attachments.data(),
|
||||
.blendConstants = {}
|
||||
};
|
||||
|
||||
// Dynamic states configuration based on feature support
|
||||
static_vector<VkDynamicState, 34> dynamic_states;
|
||||
|
||||
// Core dynamic states (Vulkan 1.0)
|
||||
if (key.state.dynamic_state_enabled) {
|
||||
static constexpr std::array core_states{
|
||||
VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR,
|
||||
VK_DYNAMIC_STATE_DEPTH_BIAS, VK_DYNAMIC_STATE_BLEND_CONSTANTS,
|
||||
VK_DYNAMIC_STATE_DEPTH_BOUNDS, VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK,
|
||||
VK_DYNAMIC_STATE_STENCIL_WRITE_MASK, VK_DYNAMIC_STATE_STENCIL_REFERENCE,
|
||||
VK_DYNAMIC_STATE_LINE_WIDTH,
|
||||
};
|
||||
dynamic_states.insert(dynamic_states.end(), core_states.begin(), core_states.end());
|
||||
}
|
||||
|
||||
static_vector<VkDynamicState, 34> dynamic_states{
|
||||
VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR,
|
||||
VK_DYNAMIC_STATE_DEPTH_BIAS, VK_DYNAMIC_STATE_BLEND_CONSTANTS,
|
||||
VK_DYNAMIC_STATE_DEPTH_BOUNDS, VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK,
|
||||
VK_DYNAMIC_STATE_STENCIL_WRITE_MASK, VK_DYNAMIC_STATE_STENCIL_REFERENCE,
|
||||
VK_DYNAMIC_STATE_LINE_WIDTH,
|
||||
};
|
||||
if (key.state.extended_dynamic_state) {
|
||||
static constexpr std::array extended{
|
||||
VK_DYNAMIC_STATE_CULL_MODE_EXT,
|
||||
@@ -854,13 +846,15 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
|
||||
};
|
||||
dynamic_states.insert(dynamic_states.end(), extended.begin(), extended.end());
|
||||
|
||||
// VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT
|
||||
// VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT is part of EDS1
|
||||
// Only use it if VIDS is not active (VIDS replaces it with full vertex input control)
|
||||
if (!key.state.dynamic_vertex_input) {
|
||||
dynamic_states.push_back(VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT);
|
||||
}
|
||||
}
|
||||
|
||||
// VK_DYNAMIC_STATE_VERTEX_INPUT_EXT
|
||||
// VK_DYNAMIC_STATE_VERTEX_INPUT_EXT (VIDS) - Independent from EDS
|
||||
// Provides full dynamic vertex input control, replaces VERTEX_INPUT_BINDING_STRIDE
|
||||
if (key.state.dynamic_vertex_input) {
|
||||
dynamic_states.push_back(VK_DYNAMIC_STATE_VERTEX_INPUT_EXT);
|
||||
}
|
||||
@@ -915,10 +909,6 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
|
||||
}
|
||||
}
|
||||
|
||||
if (device.IsExtProvokingVertexDynamicStateSupported()) {
|
||||
dynamic_states.push_back(VK_DYNAMIC_STATE_PROVOKING_VERTEX_MODE_EXT);
|
||||
}
|
||||
|
||||
const VkPipelineDynamicStateCreateInfo dynamic_state_ci{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
|
||||
@@ -437,7 +437,13 @@ PipelineCache::PipelineCache(Tegra::MaxwellDeviceMemoryManager& device_memory_,
|
||||
|
||||
dynamic_features = {};
|
||||
|
||||
dynamic_features.has_dynamic_state = device.IsCoreDynamicStateSupported();
|
||||
// User granularity enforced in vulkan_device.cpp switch statement:
|
||||
// Level 0: Core Dynamic States only
|
||||
// Level 1: Core + EDS1
|
||||
// Level 2: Core + EDS1 + EDS2 (accumulative)
|
||||
// Level 3: Core + EDS1 + EDS2 + EDS3 (accumulative)
|
||||
// Here we only verify if extensions were successfully loaded by the device
|
||||
|
||||
dynamic_features.has_extended_dynamic_state =
|
||||
device.IsExtExtendedDynamicStateSupported();
|
||||
|
||||
|
||||
@@ -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-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
|
||||
@@ -61,26 +61,6 @@ struct DrawParams {
|
||||
bool is_indexed;
|
||||
};
|
||||
|
||||
VkViewport ClampViewport(const Device& device, VkViewport viewport) {
|
||||
const auto max_dims = device.GetMaxViewportDimensions();
|
||||
const auto bounds = device.GetViewportBoundsRange();
|
||||
const auto clamp_abs = [](float value, float max_abs) {
|
||||
const float clamped = std::min(std::abs(value), max_abs);
|
||||
return std::copysign(clamped, value);
|
||||
};
|
||||
|
||||
viewport.width = viewport.width == 0.0f ? 1.0f : viewport.width;
|
||||
viewport.height = viewport.height == 0.0f ? 1.0f : viewport.height;
|
||||
|
||||
viewport.width = clamp_abs(viewport.width, static_cast<float>(max_dims[0]));
|
||||
viewport.height = clamp_abs(viewport.height, static_cast<float>(max_dims[1]));
|
||||
|
||||
viewport.x = std::clamp(viewport.x, bounds[0], bounds[1]);
|
||||
viewport.y = std::clamp(viewport.y, bounds[0], bounds[1]);
|
||||
|
||||
return viewport;
|
||||
}
|
||||
|
||||
VkViewport GetViewportState(const Device& device, const Maxwell& regs, size_t index, float scale) {
|
||||
const auto& src = regs.viewport_transform[index];
|
||||
const auto conv = [scale](float value) {
|
||||
@@ -126,7 +106,7 @@ VkViewport GetViewportState(const Device& device, const Maxwell& regs, size_t in
|
||||
viewport.minDepth = std::clamp(viewport.minDepth, 0.0f, 1.0f);
|
||||
viewport.maxDepth = std::clamp(viewport.maxDepth, 0.0f, 1.0f);
|
||||
}
|
||||
return ClampViewport(device, viewport);
|
||||
return viewport;
|
||||
}
|
||||
|
||||
VkRect2D GetScissorState(const Maxwell& regs, size_t index, u32 up_scale = 1, u32 down_shift = 0) {
|
||||
@@ -243,11 +223,6 @@ void RasterizerVulkan::PrepareDraw(bool is_indexed, Func&& draw_func) {
|
||||
return;
|
||||
}
|
||||
std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex};
|
||||
buffer_cache_runtime.SetUseDynamicVertexBindingStride(
|
||||
pipeline->UsesExtendedDynamicState() && !pipeline->HasDynamicVertexInput());
|
||||
if (device.IsExtProvokingVertexDynamicStateSupported()) {
|
||||
state_tracker.InvalidateProvokingVertex();
|
||||
}
|
||||
// update engine as channel may be different.
|
||||
pipeline->SetEngine(maxwell3d, gpu_memory);
|
||||
if (!pipeline->Configure(is_indexed))
|
||||
@@ -1034,16 +1009,16 @@ bool AccelerateDMA::BufferToImage(const Tegra::DMA::ImageCopy& copy_info,
|
||||
void RasterizerVulkan::UpdateDynamicStates() {
|
||||
auto& regs = maxwell3d->regs;
|
||||
|
||||
if (device.IsCoreDynamicStateSupported()) {
|
||||
UpdateViewportsState(regs);
|
||||
UpdateScissorsState(regs);
|
||||
UpdateDepthBias(regs);
|
||||
UpdateBlendConstants(regs);
|
||||
UpdateDepthBounds(regs);
|
||||
UpdateStencilFaces(regs);
|
||||
UpdateLineWidth(regs);
|
||||
}
|
||||
// Core Dynamic States (Vulkan 1.0) - Always active regardless of dyna_state setting
|
||||
UpdateViewportsState(regs);
|
||||
UpdateScissorsState(regs);
|
||||
UpdateDepthBias(regs);
|
||||
UpdateBlendConstants(regs);
|
||||
UpdateDepthBounds(regs);
|
||||
UpdateStencilFaces(regs);
|
||||
UpdateLineWidth(regs);
|
||||
|
||||
// EDS1: CullMode, DepthCompare, FrontFace, StencilOp, DepthBoundsTest, DepthTest, DepthWrite, StencilTest
|
||||
if (device.IsExtExtendedDynamicStateSupported()) {
|
||||
UpdateCullMode(regs);
|
||||
UpdateDepthCompareOp(regs);
|
||||
@@ -1057,22 +1032,22 @@ void RasterizerVulkan::UpdateDynamicStates() {
|
||||
}
|
||||
}
|
||||
|
||||
// EDS2: PrimitiveRestart, RasterizerDiscard, DepthBias enable/disable
|
||||
if (device.IsExtExtendedDynamicState2Supported()) {
|
||||
UpdatePrimitiveRestartEnable(regs);
|
||||
UpdateRasterizerDiscardEnable(regs);
|
||||
UpdateDepthBiasEnable(regs);
|
||||
}
|
||||
|
||||
// EDS2 Extras: LogicOp operation selection
|
||||
if (device.IsExtExtendedDynamicState2ExtrasSupported()) {
|
||||
UpdateLogicOp(regs);
|
||||
}
|
||||
|
||||
if (device.IsExtProvokingVertexDynamicStateSupported()) {
|
||||
UpdateProvokingVertex(regs);
|
||||
}
|
||||
|
||||
// EDS3 Enables: LogicOpEnable, DepthClamp, LineStipple, ConservativeRaster
|
||||
if (device.IsExtExtendedDynamicState3EnablesSupported()) {
|
||||
using namespace Tegra::Engines;
|
||||
// AMD Workaround: LogicOp incompatible with float render targets
|
||||
if (device.GetDriverID() == VkDriverIdKHR::VK_DRIVER_ID_AMD_OPEN_SOURCE ||
|
||||
device.GetDriverID() == VkDriverIdKHR::VK_DRIVER_ID_AMD_PROPRIETARY) {
|
||||
const auto has_float = std::any_of(
|
||||
@@ -1094,10 +1069,12 @@ void RasterizerVulkan::UpdateDynamicStates() {
|
||||
UpdateAlphaToOneEnable(regs);
|
||||
}
|
||||
|
||||
// EDS3 Blending: ColorBlendEnable, ColorBlendEquation, ColorWriteMask
|
||||
if (device.IsExtExtendedDynamicState3BlendingSupported()) {
|
||||
UpdateBlending(regs);
|
||||
}
|
||||
|
||||
// Vertex Input Dynamic State: Independent from EDS levels
|
||||
if (device.IsExtVertexInputDynamicStateSupported()) {
|
||||
if (auto* gp = pipeline_cache.CurrentGraphicsPipeline(); gp && gp->HasDynamicVertexInput()) {
|
||||
UpdateVertexInput(regs);
|
||||
@@ -1156,9 +1133,8 @@ void RasterizerVulkan::UpdateViewportsState(Tegra::Engines::Maxwell3D::Regs& reg
|
||||
.minDepth = 0.0f,
|
||||
.maxDepth = 1.0f,
|
||||
};
|
||||
const VkViewport clamped = ClampViewport(device, viewport);
|
||||
scheduler.Record([clamped](vk::CommandBuffer cmdbuf) {
|
||||
cmdbuf.SetViewport(0, clamped);
|
||||
scheduler.Record([viewport](vk::CommandBuffer cmdbuf) {
|
||||
cmdbuf.SetViewport(0, viewport);
|
||||
});
|
||||
return;
|
||||
}
|
||||
@@ -1647,20 +1623,6 @@ void RasterizerVulkan::UpdateFrontFace(Tegra::Engines::Maxwell3D::Regs& regs) {
|
||||
[front_face](vk::CommandBuffer cmdbuf) { cmdbuf.SetFrontFaceEXT(front_face); });
|
||||
}
|
||||
|
||||
void RasterizerVulkan::UpdateProvokingVertex(Tegra::Engines::Maxwell3D::Regs& regs) {
|
||||
if (!device.IsExtProvokingVertexSupported()) {
|
||||
return;
|
||||
}
|
||||
if (!state_tracker.TouchProvokingVertex()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto mode = regs.provoking_vertex == Maxwell::ProvokingVertex::Last
|
||||
? VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT
|
||||
: VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT;
|
||||
scheduler.Record([mode](vk::CommandBuffer cmdbuf) { cmdbuf.SetProvokingVertexEXT(mode); });
|
||||
}
|
||||
|
||||
void RasterizerVulkan::UpdateStencilOp(Tegra::Engines::Maxwell3D::Regs& regs) {
|
||||
if (!state_tracker.TouchStencilOp()) {
|
||||
return;
|
||||
@@ -1711,28 +1673,26 @@ void RasterizerVulkan::UpdateBlending(Tegra::Engines::Maxwell3D::Regs& regs) {
|
||||
}
|
||||
|
||||
if (state_tracker.TouchColorMask()) {
|
||||
if (device.IsExtExtendedDynamicState3BlendingSupported()) {
|
||||
std::array<VkColorComponentFlags, Maxwell::NumRenderTargets> setup_masks{};
|
||||
for (size_t index = 0; index < Maxwell::NumRenderTargets; index++) {
|
||||
const auto& mask = regs.color_mask[regs.color_mask_common ? 0 : index];
|
||||
auto& current = setup_masks[index];
|
||||
if (mask.R) {
|
||||
current |= VK_COLOR_COMPONENT_R_BIT;
|
||||
}
|
||||
if (mask.G) {
|
||||
current |= VK_COLOR_COMPONENT_G_BIT;
|
||||
}
|
||||
if (mask.B) {
|
||||
current |= VK_COLOR_COMPONENT_B_BIT;
|
||||
}
|
||||
if (mask.A) {
|
||||
current |= VK_COLOR_COMPONENT_A_BIT;
|
||||
}
|
||||
std::array<VkColorComponentFlags, Maxwell::NumRenderTargets> setup_masks{};
|
||||
for (size_t index = 0; index < Maxwell::NumRenderTargets; index++) {
|
||||
const auto& mask = regs.color_mask[regs.color_mask_common ? 0 : index];
|
||||
auto& current = setup_masks[index];
|
||||
if (mask.R) {
|
||||
current |= VK_COLOR_COMPONENT_R_BIT;
|
||||
}
|
||||
if (mask.G) {
|
||||
current |= VK_COLOR_COMPONENT_G_BIT;
|
||||
}
|
||||
if (mask.B) {
|
||||
current |= VK_COLOR_COMPONENT_B_BIT;
|
||||
}
|
||||
if (mask.A) {
|
||||
current |= VK_COLOR_COMPONENT_A_BIT;
|
||||
}
|
||||
scheduler.Record([setup_masks](vk::CommandBuffer cmdbuf) {
|
||||
cmdbuf.SetColorWriteMaskEXT(0, setup_masks);
|
||||
});
|
||||
}
|
||||
scheduler.Record([setup_masks](vk::CommandBuffer cmdbuf) {
|
||||
cmdbuf.SetColorWriteMaskEXT(0, setup_masks);
|
||||
});
|
||||
}
|
||||
|
||||
if (state_tracker.TouchBlendEnable()) {
|
||||
|
||||
@@ -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-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
||||
@@ -186,7 +186,6 @@ private:
|
||||
void UpdateAlphaToCoverageEnable(Tegra::Engines::Maxwell3D::Regs& regs);
|
||||
void UpdateAlphaToOneEnable(Tegra::Engines::Maxwell3D::Regs& regs);
|
||||
void UpdateFrontFace(Tegra::Engines::Maxwell3D::Regs& regs);
|
||||
void UpdateProvokingVertex(Tegra::Engines::Maxwell3D::Regs& regs);
|
||||
void UpdateStencilOp(Tegra::Engines::Maxwell3D::Regs& regs);
|
||||
void UpdateStencilTestEnable(Tegra::Engines::Maxwell3D::Regs& regs);
|
||||
void UpdateLogicOp(Tegra::Engines::Maxwell3D::Regs& regs);
|
||||
|
||||
@@ -143,7 +143,6 @@ void Scheduler::RequestRenderpass(const Framebuffer* framebuffer) {
|
||||
};
|
||||
cmdbuf.BeginRenderPass(renderpass_bi, VK_SUBPASS_CONTENTS_INLINE);
|
||||
});
|
||||
|
||||
num_renderpass_images = framebuffer->NumImages();
|
||||
renderpass_images = framebuffer->Images();
|
||||
renderpass_image_ranges = framebuffer->ImageRanges();
|
||||
|
||||
@@ -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-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
||||
|
||||
@@ -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-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||
@@ -166,10 +166,6 @@ void SetupDirtyFrontFace(Tables& tables) {
|
||||
table[OFF(window_origin)] = FrontFace;
|
||||
}
|
||||
|
||||
void SetupDirtyProvokingVertex(Tables& tables) {
|
||||
tables[0][OFF(provoking_vertex)] = ProvokingVertex;
|
||||
}
|
||||
|
||||
void SetupDirtyStencilOp(Tables& tables) {
|
||||
auto& table = tables[0];
|
||||
table[OFF(stencil_front_op.fail)] = StencilOp;
|
||||
@@ -254,7 +250,6 @@ void StateTracker::SetupTables(Tegra::Control::ChannelState& channel_state) {
|
||||
SetupDirtyStateEnable(tables);
|
||||
SetupDirtyDepthCompareOp(tables);
|
||||
SetupDirtyFrontFace(tables);
|
||||
SetupDirtyProvokingVertex(tables);
|
||||
SetupDirtyStencilOp(tables);
|
||||
SetupDirtyBlending(tables);
|
||||
SetupDirtyViewportSwizzles(tables);
|
||||
|
||||
@@ -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-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||
@@ -49,7 +49,6 @@ enum : u8 {
|
||||
DepthWriteEnable,
|
||||
DepthCompareOp,
|
||||
FrontFace,
|
||||
ProvokingVertex,
|
||||
StencilOp,
|
||||
StencilTestEnable,
|
||||
PrimitiveRestartEnable,
|
||||
@@ -102,10 +101,6 @@ public:
|
||||
(*flags)[Dirty::StateEnable] = true;
|
||||
}
|
||||
|
||||
void InvalidateProvokingVertex() {
|
||||
(*flags)[Dirty::ProvokingVertex] = true;
|
||||
}
|
||||
|
||||
bool TouchViewports() {
|
||||
const bool dirty_viewports = Exchange(Dirty::Viewports, false);
|
||||
const bool rescale_viewports = Exchange(VideoCommon::Dirty::RescaleViewports, false);
|
||||
@@ -253,10 +248,6 @@ public:
|
||||
return Exchange(Dirty::FrontFace, false);
|
||||
}
|
||||
|
||||
bool TouchProvokingVertex() {
|
||||
return Exchange(Dirty::ProvokingVertex, false);
|
||||
}
|
||||
|
||||
bool TouchStencilOp() {
|
||||
return Exchange(Dirty::StencilOp, false);
|
||||
}
|
||||
|
||||
@@ -848,13 +848,11 @@ TextureCacheRuntime::TextureCacheRuntime(const Device& device_, Scheduler& sched
|
||||
RenderPassCache& render_pass_cache_,
|
||||
DescriptorPool& descriptor_pool,
|
||||
ComputePassDescriptorQueue& compute_pass_descriptor_queue)
|
||||
: device{device_}, scheduler{scheduler_}, memory_allocator{memory_allocator_},
|
||||
staging_buffer_pool{staging_buffer_pool_}, blit_image_helper{blit_image_helper_},
|
||||
render_pass_cache{render_pass_cache_}, resolution{Settings::values.resolution_info} {
|
||||
if (Settings::values.accelerate_astc.GetValue() == Settings::AstcDecodeMode::Gpu) {
|
||||
astc_decoder_pass.emplace(device, scheduler, descriptor_pool, staging_buffer_pool,
|
||||
compute_pass_descriptor_queue, memory_allocator);
|
||||
}
|
||||
: device{device_}, scheduler{scheduler_}, memory_allocator{memory_allocator_}
|
||||
, staging_buffer_pool{staging_buffer_pool_}, blit_image_helper{blit_image_helper_}
|
||||
, render_pass_cache{render_pass_cache_}, resolution{Settings::values.resolution_info}
|
||||
{
|
||||
astc_decoder_pass.emplace(device, scheduler, descriptor_pool, staging_buffer_pool, compute_pass_descriptor_queue, memory_allocator);
|
||||
if (device.IsStorageImageMultisampleSupported()) {
|
||||
msaa_copy_pass.emplace(device, scheduler, descriptor_pool, staging_buffer_pool, compute_pass_descriptor_queue);
|
||||
}
|
||||
@@ -1562,20 +1560,8 @@ Image::Image(TextureCacheRuntime& runtime_, const ImageInfo& info_, GPUVAddr gpu
|
||||
runtime->ViewFormats(info.format))),
|
||||
aspect_mask(ImageAspectMask(info.format)) {
|
||||
if (IsPixelFormatASTC(info.format) && !runtime->device.IsOptimalAstcSupported()) {
|
||||
switch (Settings::values.accelerate_astc.GetValue()) {
|
||||
case Settings::AstcDecodeMode::Gpu:
|
||||
if (Settings::values.astc_recompression.GetValue() ==
|
||||
Settings::AstcRecompression::Uncompressed &&
|
||||
info.size.depth == 1) {
|
||||
flags |= VideoCommon::ImageFlagBits::AcceleratedUpload;
|
||||
}
|
||||
break;
|
||||
case Settings::AstcDecodeMode::CpuAsynchronous:
|
||||
flags |= VideoCommon::ImageFlagBits::AsynchronousDecode;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ASSERT(info.size.depth == 1 && "ASTC Image depth >1 isn't supported");
|
||||
flags |= VideoCommon::ImageFlagBits::AcceleratedUpload;
|
||||
flags |= VideoCommon::ImageFlagBits::Converted;
|
||||
flags |= VideoCommon::ImageFlagBits::CostlyLoad;
|
||||
}
|
||||
@@ -1588,13 +1574,10 @@ Image::Image(TextureCacheRuntime& runtime_, const ImageInfo& info_, GPUVAddr gpu
|
||||
}
|
||||
current_image = &Image::original_image;
|
||||
storage_image_views.resize(info.resources.levels);
|
||||
if (IsPixelFormatASTC(info.format) && !runtime->device.IsOptimalAstcSupported() &&
|
||||
Settings::values.astc_recompression.GetValue() ==
|
||||
Settings::AstcRecompression::Uncompressed) {
|
||||
if (IsPixelFormatASTC(info.format) && !runtime->device.IsOptimalAstcSupported()) {
|
||||
const auto& device = runtime->device.GetLogical();
|
||||
for (s32 level = 0; level < info.resources.levels; ++level) {
|
||||
storage_image_views[level] =
|
||||
MakeStorageView(device, level, *original_image, VK_FORMAT_A8B8G8R8_UNORM_PACK32);
|
||||
storage_image_views[level] = MakeStorageView(device, level, *original_image, VK_FORMAT_A8B8G8R8_UNORM_PACK32);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2115,18 +2098,14 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
|
||||
"Image view format {} has different usage flags than image format {}", format,
|
||||
image.info.format);
|
||||
}
|
||||
|
||||
const VkImageViewUsageCreateInfo image_view_usage{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.usage = ImageUsageFlags(format_info, format),
|
||||
};
|
||||
|
||||
const void* view_pNext = &image_view_usage;
|
||||
|
||||
const VkImageViewCreateInfo create_info{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
||||
.pNext = view_pNext,
|
||||
.pNext = &image_view_usage,
|
||||
.flags = 0,
|
||||
.image = image.Handle(),
|
||||
.viewType = VkImageViewType{},
|
||||
@@ -2456,19 +2435,16 @@ void TextureCacheRuntime::AccelerateImageUpload(
|
||||
std::span<const VideoCommon::SwizzleParameters> swizzles,
|
||||
u32 z_start, u32 z_count) {
|
||||
|
||||
if (IsPixelFormatASTC(image.info.format)) {
|
||||
if (IsPixelFormatASTC(image.info.format)
|
||||
&& image.info.type == ImageType::e2D) {
|
||||
return astc_decoder_pass->Assemble(image, map, swizzles);
|
||||
}
|
||||
|
||||
if (bl3d_unswizzle_pass &&
|
||||
IsPixelFormatBCn(image.info.format) &&
|
||||
image.info.type == ImageType::e3D &&
|
||||
image.info.resources.levels == 1 &&
|
||||
image.info.resources.layers == 1) {
|
||||
|
||||
if (IsPixelFormatBCn(image.info.format)
|
||||
&& image.info.type == ImageType::e3D
|
||||
&& image.info.resources.levels == 1
|
||||
&& image.info.resources.layers == 1) {
|
||||
return bl3d_unswizzle_pass->Unswizzle(image, map, swizzles, z_start, z_count);
|
||||
}
|
||||
|
||||
ASSERT(false);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: 2014 Citra Emulator Project
|
||||
@@ -444,15 +444,17 @@ std::pair<u32, u32> GetASTCBlockSize(PixelFormat format) {
|
||||
|
||||
u64 TranscodedAstcSize(u64 base_size, PixelFormat format) {
|
||||
constexpr u64 RGBA8_PIXEL_SIZE = 4;
|
||||
const u64 base_block_size = static_cast<u64>(DefaultBlockWidth(format)) *
|
||||
static_cast<u64>(DefaultBlockHeight(format)) * RGBA8_PIXEL_SIZE;
|
||||
const u64 base_block_size = u64(DefaultBlockWidth(format)) * u64(DefaultBlockHeight(format)) * RGBA8_PIXEL_SIZE;
|
||||
const u64 uncompressed_size = (base_size * base_block_size) / BytesPerBlock(format);
|
||||
|
||||
switch (Settings::values.astc_recompression.GetValue()) {
|
||||
case Settings::AstcRecompression::Bc1:
|
||||
return uncompressed_size / 8;
|
||||
case Settings::AstcRecompression::Bc3:
|
||||
return uncompressed_size / 4;
|
||||
case Settings::AstcRecompression::Bc7:
|
||||
return uncompressed_size / 4;
|
||||
case Settings::AstcRecompression::Etc2:
|
||||
return uncompressed_size / 4; //6=RGB, 4=RGBA
|
||||
default:
|
||||
return uncompressed_size;
|
||||
}
|
||||
|
||||
@@ -2317,13 +2317,10 @@ ImageViewId TextureCache<P>::FindOrEmplaceImageView(ImageId image_id, const Imag
|
||||
template <class P>
|
||||
void TextureCache<P>::RegisterImage(ImageId image_id) {
|
||||
ImageBase& image = slot_images[image_id];
|
||||
ASSERT_MSG(False(image.flags & ImageFlagBits::Registered),
|
||||
"Trying to register an already registered image");
|
||||
ASSERT(False(image.flags & ImageFlagBits::Registered) && "Trying to register an already registered image");
|
||||
image.flags |= ImageFlagBits::Registered;
|
||||
u64 tentative_size = (std::max)(image.guest_size_bytes, image.unswizzled_size_bytes);
|
||||
if ((IsPixelFormatASTC(image.info.format) &&
|
||||
True(image.flags & ImageFlagBits::AcceleratedUpload)) ||
|
||||
True(image.flags & ImageFlagBits::Converted)) {
|
||||
if ((IsPixelFormatASTC(image.info.format) && True(image.flags & ImageFlagBits::AcceleratedUpload)) || True(image.flags & ImageFlagBits::Converted)) {
|
||||
tentative_size = TranscodedAstcSize(tentative_size, image.info.format);
|
||||
}
|
||||
total_used_memory += Common::AlignUp(tentative_size, 1024);
|
||||
@@ -2495,9 +2492,7 @@ void TextureCache<P>::DeleteImage(ImageId image_id, bool immediate_delete) {
|
||||
total_used_memory -= GetScaledImageSizeBytes(image);
|
||||
}
|
||||
u64 tentative_size = (std::max)(image.guest_size_bytes, image.unswizzled_size_bytes);
|
||||
if ((IsPixelFormatASTC(image.info.format) &&
|
||||
True(image.flags & ImageFlagBits::AcceleratedUpload)) ||
|
||||
True(image.flags & ImageFlagBits::Converted)) {
|
||||
if ((IsPixelFormatASTC(image.info.format) && True(image.flags & ImageFlagBits::AcceleratedUpload)) || True(image.flags & ImageFlagBits::Converted)) {
|
||||
tentative_size = TranscodedAstcSize(tentative_size, image.info.format);
|
||||
}
|
||||
total_used_memory -= Common::AlignUp(tentative_size, 1024);
|
||||
|
||||
@@ -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-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||
@@ -33,7 +33,6 @@
|
||||
#include "video_core/texture_cache/formatter.h"
|
||||
#include "video_core/texture_cache/samples_helper.h"
|
||||
#include "video_core/texture_cache/util.h"
|
||||
#include "video_core/textures/astc.h"
|
||||
#include "video_core/textures/bcn.h"
|
||||
#include "video_core/textures/decoders.h"
|
||||
|
||||
@@ -608,23 +607,18 @@ u32 CalculateConvertedSizeBytes(const ImageInfo& info) noexcept {
|
||||
return info.size.width * BytesPerBlock(info.format);
|
||||
}
|
||||
static constexpr Extent2D TILE_SIZE{1, 1};
|
||||
if (IsPixelFormatASTC(info.format) && Settings::values.astc_recompression.GetValue() !=
|
||||
Settings::AstcRecompression::Uncompressed) {
|
||||
const u32 bpp_div =
|
||||
Settings::values.astc_recompression.GetValue() == Settings::AstcRecompression::Bc1 ? 2
|
||||
: 1;
|
||||
if (IsPixelFormatASTC(info.format) && Settings::values.astc_recompression.GetValue() != Settings::AstcRecompression::Uncompressed) {
|
||||
const u32 bpp_div = Settings::values.astc_recompression.GetValue() == Settings::AstcRecompression::Bc1 ? 2 : 1;
|
||||
// NumBlocksPerLayer doesn't account for this correctly, so we have to do it manually.
|
||||
u32 output_size = 0;
|
||||
for (s32 i = 0; i < info.resources.levels; i++) {
|
||||
const auto mip_size = AdjustMipSize(info.size, i);
|
||||
const u32 plane_dim =
|
||||
Common::AlignUp(mip_size.width, 4U) * Common::AlignUp(mip_size.height, 4U);
|
||||
const u32 plane_dim = Common::AlignUp(mip_size.width, 4U) * Common::AlignUp(mip_size.height, 4U);
|
||||
output_size += (plane_dim * info.size.depth * info.resources.layers) / bpp_div;
|
||||
}
|
||||
return output_size;
|
||||
}
|
||||
return NumBlocksPerLayer(info, TILE_SIZE) * info.resources.layers *
|
||||
ConvertedBytesPerBlock(info.format);
|
||||
return NumBlocksPerLayer(info, TILE_SIZE) * info.resources.layers * ConvertedBytesPerBlock(info.format);
|
||||
}
|
||||
|
||||
u32 CalculateLayerStride(const ImageInfo& info) noexcept {
|
||||
@@ -922,8 +916,7 @@ boost::container::small_vector<BufferImageCopy, 16> UnswizzleImage(Tegra::Memory
|
||||
return copies;
|
||||
}
|
||||
|
||||
void ConvertImage(std::span<const u8> input, const ImageInfo& info, std::span<u8> output,
|
||||
std::span<BufferImageCopy> copies) {
|
||||
void ConvertImage(std::span<const u8> input, const ImageInfo& info, std::span<u8> output, std::span<BufferImageCopy> copies) {
|
||||
u32 output_offset = 0;
|
||||
Common::ScratchBuffer<u8> decode_scratch;
|
||||
|
||||
@@ -939,56 +932,9 @@ void ConvertImage(std::span<const u8> input, const ImageInfo& info, std::span<u8
|
||||
|
||||
const auto input_offset = input.subspan(copy.buffer_offset);
|
||||
copy.buffer_offset = output_offset;
|
||||
|
||||
const auto recompression_setting = Settings::values.astc_recompression.GetValue();
|
||||
const bool astc = IsPixelFormatASTC(info.format);
|
||||
|
||||
if (astc && recompression_setting == Settings::AstcRecompression::Uncompressed) {
|
||||
Tegra::Texture::ASTC::Decompress(
|
||||
input_offset, copy.image_extent.width, copy.image_extent.height,
|
||||
copy.image_subresource.num_layers * copy.image_extent.depth, tile_size.width,
|
||||
tile_size.height, output.subspan(output_offset));
|
||||
|
||||
output_offset += copy.image_extent.width * copy.image_extent.height *
|
||||
copy.image_subresource.num_layers *
|
||||
BytesPerBlock(PixelFormat::A8B8G8R8_UNORM);
|
||||
} else if (astc) {
|
||||
// BC1 uses 0.5 bytes per texel
|
||||
// BC3 uses 1 byte per texel
|
||||
const auto compress = recompression_setting == Settings::AstcRecompression::Bc1
|
||||
? Tegra::Texture::BCN::CompressBC1
|
||||
: Tegra::Texture::BCN::CompressBC3;
|
||||
const auto bpp_div = recompression_setting == Settings::AstcRecompression::Bc1 ? 2 : 1;
|
||||
|
||||
const u32 plane_dim = copy.image_extent.width * copy.image_extent.height;
|
||||
const u32 level_size = plane_dim * copy.image_extent.depth *
|
||||
copy.image_subresource.num_layers *
|
||||
BytesPerBlock(PixelFormat::A8B8G8R8_UNORM);
|
||||
decode_scratch.resize_destructive(level_size);
|
||||
|
||||
Tegra::Texture::ASTC::Decompress(
|
||||
input_offset, copy.image_extent.width, copy.image_extent.height,
|
||||
copy.image_subresource.num_layers * copy.image_extent.depth, tile_size.width,
|
||||
tile_size.height, decode_scratch);
|
||||
|
||||
compress(decode_scratch, copy.image_extent.width, copy.image_extent.height,
|
||||
copy.image_subresource.num_layers * copy.image_extent.depth,
|
||||
output.subspan(output_offset));
|
||||
|
||||
const u32 aligned_plane_dim = Common::AlignUp(copy.image_extent.width, 4) *
|
||||
Common::AlignUp(copy.image_extent.height, 4);
|
||||
|
||||
copy.buffer_size =
|
||||
(aligned_plane_dim * copy.image_extent.depth * copy.image_subresource.num_layers) /
|
||||
bpp_div;
|
||||
output_offset += static_cast<u32>(copy.buffer_size);
|
||||
} else {
|
||||
DecompressBCn(input_offset, output.subspan(output_offset), copy, info.format);
|
||||
output_offset += copy.image_extent.width * copy.image_extent.height *
|
||||
copy.image_subresource.num_layers *
|
||||
ConvertedBytesPerBlock(info.format);
|
||||
}
|
||||
|
||||
ASSERT(!IsPixelFormatASTC(info.format) && "CPU ASTC decoder is phased out");
|
||||
DecompressBCn(input_offset, output.subspan(output_offset), copy, info.format);
|
||||
output_offset += copy.image_extent.width * copy.image_extent.height * copy.image_subresource.num_layers * ConvertedBytesPerBlock(info.format);
|
||||
copy.buffer_row_length = mip_size.width;
|
||||
copy.buffer_image_height = mip_size.height;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,11 +0,0 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Tegra::Texture::ASTC {
|
||||
|
||||
void Decompress(std::span<const uint8_t> data, uint32_t width, uint32_t height, uint32_t depth,
|
||||
uint32_t block_width, uint32_t block_height, std::span<uint8_t> output);
|
||||
|
||||
} // namespace Tegra::Texture::ASTC
|
||||
@@ -448,7 +448,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
||||
|
||||
// GetSuitability has already configured the linked list of features for us.
|
||||
// Reuse it here.
|
||||
void* first_next = &features2;
|
||||
const void* first_next = &features2;
|
||||
|
||||
VkDeviceDiagnosticsConfigCreateInfoNV diagnostics_nv{};
|
||||
const bool use_diagnostics_nv = Settings::values.enable_nsight_aftermath && extensions.device_diagnostics_config;
|
||||
@@ -465,6 +465,18 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
||||
first_next = &diagnostics_nv;
|
||||
}
|
||||
|
||||
VkPhysicalDeviceDescriptorIndexingFeaturesEXT descriptor_indexing{
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT,
|
||||
.pNext = use_diagnostics_nv ? static_cast<void*>(&diagnostics_nv) : static_cast<void*>(&features2),
|
||||
.shaderSampledImageArrayNonUniformIndexing = VK_TRUE,
|
||||
.descriptorBindingPartiallyBound = VK_TRUE,
|
||||
.descriptorBindingVariableDescriptorCount = VK_TRUE,
|
||||
};
|
||||
|
||||
if (extensions.descriptor_indexing && Settings::values.descriptor_indexing.GetValue()) {
|
||||
first_next = &descriptor_indexing;
|
||||
}
|
||||
|
||||
is_blit_depth24_stencil8_supported = TestDepthStencilBlits(VK_FORMAT_D24_UNORM_S8_UINT);
|
||||
is_blit_depth32_stencil8_supported = TestDepthStencilBlits(VK_FORMAT_D32_SFLOAT_S8_UINT);
|
||||
is_optimal_astc_supported = ComputeIsOptimalAstcSupported();
|
||||
@@ -486,24 +498,19 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
||||
CollectToolingInfo();
|
||||
|
||||
if (is_qualcomm) {
|
||||
// Qualcomm Adreno GPUs doesn't handle scaled vertex attributes; keep emulation enabled
|
||||
must_emulate_scaled_formats = true;
|
||||
LOG_WARNING(Render_Vulkan,
|
||||
"Qualcomm drivers require scaled vertex format emulation");
|
||||
"Qualcomm drivers require scaled vertex format emulation; forcing fallback");
|
||||
|
||||
LOG_WARNING(Render_Vulkan,
|
||||
"Disabling shaderFloatControls and 64-bit integer features on Qualcomm proprietary drivers");
|
||||
"Disabling shader float controls and 64-bit integer features on Qualcomm proprietary drivers");
|
||||
RemoveExtension(extensions.shader_float_controls, VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME);
|
||||
RemoveExtensionFeature(extensions.shader_atomic_int64, features.shader_atomic_int64,
|
||||
VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME);
|
||||
features.shader_atomic_int64.shaderBufferInt64Atomics = false;
|
||||
features.shader_atomic_int64.shaderSharedInt64Atomics = false;
|
||||
features.features.shaderInt64 = false;
|
||||
LOG_WARNING(Render_Vulkan,
|
||||
"Disabling shaderFloat16 on Qualcomm proprietary drivers");
|
||||
features.shader_float16_int8.shaderFloat16 = false;
|
||||
|
||||
sets_per_pool = 128;
|
||||
LOG_INFO(Render_Vulkan, "Qualcomm: forcing {} sets per pool", sets_per_pool);
|
||||
|
||||
#if defined(ANDROID) && defined(ARCHITECTURE_arm64)
|
||||
// BCn patching only safe on Android 9+ (API 28+). Older versions crash on driver load.
|
||||
@@ -653,9 +660,16 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
||||
|
||||
const auto dyna_state = Settings::values.dyna_state.GetValue();
|
||||
|
||||
// Base dynamic states (VIEWPORT, SCISSOR, DEPTH_BIAS, etc.) are ALWAYS active in vk_graphics_pipeline.cpp
|
||||
// This slider controls EXTENDED dynamic states with accumulative levels per Vulkan specs:
|
||||
// Level 0 = Core Dynamic States only (Vulkan 1.0)
|
||||
// Level 1 = Core + VK_EXT_extended_dynamic_state
|
||||
// Level 2 = Core + VK_EXT_extended_dynamic_state + VK_EXT_extended_dynamic_state2
|
||||
// Level 3 = Core + VK_EXT_extended_dynamic_state + VK_EXT_extended_dynamic_state2 + VK_EXT_extended_dynamic_state3
|
||||
|
||||
switch (dyna_state) {
|
||||
case Settings::ExtendedDynamicState::Core:
|
||||
LOG_INFO(Render_Vulkan, "DynamicState - Enabled");
|
||||
case Settings::ExtendedDynamicState::Disabled:
|
||||
// Level 0: Disable all extended dynamic state extensions
|
||||
RemoveExtensionFeature(extensions.extended_dynamic_state, features.extended_dynamic_state,
|
||||
VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
|
||||
RemoveExtensionFeature(extensions.extended_dynamic_state2, features.extended_dynamic_state2,
|
||||
@@ -664,53 +678,31 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
||||
VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
|
||||
dynamic_state3_blending = false;
|
||||
dynamic_state3_enables = false;
|
||||
dynamic_state3_depth_clamp_enable = false;
|
||||
dynamic_state3_logic_op_enable = false;
|
||||
dynamic_state3_line_raster_mode = false;
|
||||
dynamic_state3_conservative_raster_mode = false;
|
||||
dynamic_state3_line_stipple_enable = false;
|
||||
dynamic_state3_alpha_to_coverage = false;
|
||||
dynamic_state3_alpha_to_one = false;
|
||||
dynamic_state3_provoking_vertex_mode = false;
|
||||
break;
|
||||
case Settings::ExtendedDynamicState::EDS1:
|
||||
LOG_INFO(Render_Vulkan, "ExtededDynamicState1 - Enabled");
|
||||
// Level 1: Enable EDS1, disable EDS2 and EDS3
|
||||
RemoveExtensionFeature(extensions.extended_dynamic_state2, features.extended_dynamic_state2,
|
||||
VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
|
||||
RemoveExtensionFeature(extensions.extended_dynamic_state3, features.extended_dynamic_state3,
|
||||
VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
|
||||
dynamic_state3_blending = false;
|
||||
dynamic_state3_enables = false;
|
||||
dynamic_state3_depth_clamp_enable = false;
|
||||
dynamic_state3_logic_op_enable = false;
|
||||
dynamic_state3_line_raster_mode = false;
|
||||
dynamic_state3_conservative_raster_mode = false;
|
||||
dynamic_state3_line_stipple_enable = false;
|
||||
dynamic_state3_alpha_to_coverage = false;
|
||||
dynamic_state3_alpha_to_one = false;
|
||||
dynamic_state3_provoking_vertex_mode = false;
|
||||
break;
|
||||
case Settings::ExtendedDynamicState::EDS2:
|
||||
LOG_INFO(Render_Vulkan, "ExtededDynamicState2 - Enabled");
|
||||
// Level 2: Enable EDS1 + EDS2, disable EDS3
|
||||
RemoveExtensionFeature(extensions.extended_dynamic_state3, features.extended_dynamic_state3,
|
||||
VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
|
||||
dynamic_state3_blending = false;
|
||||
dynamic_state3_enables = false;
|
||||
dynamic_state3_depth_clamp_enable = false;
|
||||
dynamic_state3_logic_op_enable = false;
|
||||
dynamic_state3_line_raster_mode = false;
|
||||
dynamic_state3_conservative_raster_mode = false;
|
||||
dynamic_state3_line_stipple_enable = false;
|
||||
dynamic_state3_alpha_to_coverage = false;
|
||||
dynamic_state3_alpha_to_one = false;
|
||||
dynamic_state3_provoking_vertex_mode = false;
|
||||
break;
|
||||
case Settings::ExtendedDynamicState::EDS3:
|
||||
default:
|
||||
LOG_INFO(Render_Vulkan, "ExtededDynamicState3 - Enabled");
|
||||
// Level 3: Enable all (EDS1 + EDS2 + EDS3)
|
||||
break;
|
||||
}
|
||||
|
||||
// VK_EXT_vertex_input_dynamic_state is independent from EDS
|
||||
// It can be enabled even without extended_dynamic_state
|
||||
if (!Settings::values.vertex_input_dynamic_state.GetValue()) {
|
||||
RemoveExtensionFeature(extensions.vertex_input_dynamic_state, features.vertex_input_dynamic_state, VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
|
||||
}
|
||||
@@ -935,25 +927,6 @@ bool Device::HasTimelineSemaphore() const {
|
||||
if (GetDriverID() == VK_DRIVER_ID_MESA_TURNIP) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (GetDriverID() == VK_DRIVER_ID_QUALCOMM_PROPRIETARY) {
|
||||
const std::string model_name = properties.properties.deviceName;
|
||||
static constexpr std::array<const char*, 4> banned_models{
|
||||
"SM8150",
|
||||
"SM8150-AC",
|
||||
"SM8250",
|
||||
"SM8250-AC",
|
||||
};
|
||||
for (const char* banned : banned_models) {
|
||||
if (model_name.find(banned) != std::string::npos) {
|
||||
LOG_WARNING(Render_Vulkan,
|
||||
"Disabling timeline semaphores on Qualcomm model {}",
|
||||
properties.properties.deviceName);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return features.timeline_semaphore.timelineSemaphore;
|
||||
}
|
||||
|
||||
@@ -1224,11 +1197,29 @@ bool Device::GetSuitability(bool requires_swapchain) {
|
||||
}
|
||||
}
|
||||
|
||||
if (u32(Settings::values.dyna_state.GetValue()) == 0) {
|
||||
LOG_INFO(Render_Vulkan, "Extended Dynamic State disabled by user setting, clearing all EDS features");
|
||||
features.custom_border_color.customBorderColors = false;
|
||||
features.custom_border_color.customBorderColorWithoutFormat = false;
|
||||
features.extended_dynamic_state.extendedDynamicState = false;
|
||||
features.extended_dynamic_state2.extendedDynamicState2 = false;
|
||||
features.extended_dynamic_state3.extendedDynamicState3ColorBlendEnable = false;
|
||||
features.extended_dynamic_state3.extendedDynamicState3ColorBlendEquation = false;
|
||||
features.extended_dynamic_state3.extendedDynamicState3ColorWriteMask = false;
|
||||
features.extended_dynamic_state3.extendedDynamicState3DepthClampEnable = false;
|
||||
features.extended_dynamic_state3.extendedDynamicState3LogicOpEnable = false;
|
||||
}
|
||||
|
||||
// Return whether we were suitable.
|
||||
return suitable;
|
||||
}
|
||||
|
||||
void Device::RemoveUnsuitableExtensions() {
|
||||
// VK_EXT_custom_border_color
|
||||
// Enable extension if driver supports it, then check individual features
|
||||
// - customBorderColors: Required to use VK_BORDER_COLOR_FLOAT_CUSTOM_EXT
|
||||
// - customBorderColorWithoutFormat: Optional, allows VK_FORMAT_UNDEFINED
|
||||
// If only customBorderColors is available, we must provide a specific format
|
||||
if (extensions.custom_border_color) {
|
||||
// Verify that at least customBorderColors is available
|
||||
if (!features.custom_border_color.customBorderColors) {
|
||||
@@ -1252,7 +1243,7 @@ void Device::RemoveUnsuitableExtensions() {
|
||||
RemoveExtensionFeatureIfUnsuitable(extensions.depth_clip_control, features.depth_clip_control,
|
||||
VK_EXT_DEPTH_CLIP_CONTROL_EXTENSION_NAME);
|
||||
|
||||
// VK_EXT_extended_dynamic_state
|
||||
/* */ // VK_EXT_extended_dynamic_state
|
||||
extensions.extended_dynamic_state = features.extended_dynamic_state.extendedDynamicState;
|
||||
RemoveExtensionFeatureIfUnsuitable(extensions.extended_dynamic_state,
|
||||
features.extended_dynamic_state,
|
||||
@@ -1292,9 +1283,6 @@ void Device::RemoveUnsuitableExtensions() {
|
||||
const bool supports_alpha_to_one =
|
||||
features.extended_dynamic_state3.extendedDynamicState3AlphaToOneEnable &&
|
||||
features.features.alphaToOne;
|
||||
const bool supports_provoking_vertex_mode =
|
||||
features.extended_dynamic_state3.extendedDynamicState3ProvokingVertexMode &&
|
||||
extensions.provoking_vertex;
|
||||
|
||||
dynamic_state3_depth_clamp_enable = supports_depth_clamp_enable;
|
||||
dynamic_state3_logic_op_enable = supports_logic_op_enable;
|
||||
@@ -1303,14 +1291,12 @@ void Device::RemoveUnsuitableExtensions() {
|
||||
dynamic_state3_line_stipple_enable = supports_line_stipple_enable;
|
||||
dynamic_state3_alpha_to_coverage = supports_alpha_to_coverage;
|
||||
dynamic_state3_alpha_to_one = supports_alpha_to_one;
|
||||
dynamic_state3_provoking_vertex_mode = supports_provoking_vertex_mode;
|
||||
|
||||
dynamic_state3_enables = dynamic_state3_depth_clamp_enable || dynamic_state3_logic_op_enable ||
|
||||
dynamic_state3_line_raster_mode ||
|
||||
dynamic_state3_conservative_raster_mode ||
|
||||
dynamic_state3_line_stipple_enable ||
|
||||
dynamic_state3_alpha_to_coverage || dynamic_state3_alpha_to_one ||
|
||||
dynamic_state3_provoking_vertex_mode;
|
||||
dynamic_state3_alpha_to_coverage || dynamic_state3_alpha_to_one;
|
||||
|
||||
extensions.extended_dynamic_state3 = dynamic_state3_blending || dynamic_state3_enables;
|
||||
if (!extensions.extended_dynamic_state3) {
|
||||
@@ -1323,13 +1309,13 @@ void Device::RemoveUnsuitableExtensions() {
|
||||
dynamic_state3_line_stipple_enable = false;
|
||||
dynamic_state3_alpha_to_coverage = false;
|
||||
dynamic_state3_alpha_to_one = false;
|
||||
dynamic_state3_provoking_vertex_mode = false;
|
||||
}
|
||||
RemoveExtensionFeatureIfUnsuitable(extensions.extended_dynamic_state3,
|
||||
features.extended_dynamic_state3,
|
||||
VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
|
||||
|
||||
// VK_EXT_robustness2
|
||||
// Enable if at least one robustness2 feature is available
|
||||
extensions.robustness_2 = features.robustness2.robustBufferAccess2 ||
|
||||
features.robustness2.robustImageAccess2 ||
|
||||
features.robustness2.nullDescriptor;
|
||||
@@ -1338,17 +1324,24 @@ void Device::RemoveUnsuitableExtensions() {
|
||||
VK_EXT_ROBUSTNESS_2_EXTENSION_NAME);
|
||||
|
||||
// VK_EXT_image_robustness
|
||||
// Enable if robustImageAccess is available
|
||||
extensions.image_robustness = features.image_robustness.robustImageAccess;
|
||||
RemoveExtensionFeatureIfUnsuitable(extensions.image_robustness, features.image_robustness,
|
||||
VK_EXT_IMAGE_ROBUSTNESS_EXTENSION_NAME);
|
||||
|
||||
// VK_EXT_provoking_vertex
|
||||
extensions.provoking_vertex = features.provoking_vertex.provokingVertexLast
|
||||
&& features.provoking_vertex
|
||||
.transformFeedbackPreservesProvokingVertex;
|
||||
RemoveExtensionFeatureIfUnsuitable(extensions.provoking_vertex,
|
||||
features.provoking_vertex,
|
||||
VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME);
|
||||
if (Settings::values.provoking_vertex.GetValue()) {
|
||||
extensions.provoking_vertex = features.provoking_vertex.provokingVertexLast
|
||||
&& features.provoking_vertex
|
||||
.transformFeedbackPreservesProvokingVertex;
|
||||
RemoveExtensionFeatureIfUnsuitable(extensions.provoking_vertex,
|
||||
features.provoking_vertex,
|
||||
VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME);
|
||||
} else {
|
||||
RemoveExtensionFeature(extensions.provoking_vertex,
|
||||
features.provoking_vertex,
|
||||
VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME);
|
||||
}
|
||||
|
||||
// VK_KHR_shader_atomic_int64
|
||||
extensions.shader_atomic_int64 = features.shader_atomic_int64.shaderBufferInt64Atomics &&
|
||||
@@ -1373,6 +1366,10 @@ void Device::RemoveUnsuitableExtensions() {
|
||||
VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME);
|
||||
|
||||
// VK_EXT_transform_feedback
|
||||
// We only require the basic transformFeedback feature and at least
|
||||
// one transform feedback buffer. We keep transformFeedbackQueries as it's used by
|
||||
// the streaming byte count implementation. GeometryStreams and multiple streams
|
||||
// are not strictly required since we currently support only stream 0.
|
||||
extensions.transform_feedback =
|
||||
features.transform_feedback.transformFeedback &&
|
||||
properties.transform_feedback.maxTransformFeedbackBuffers > 0 &&
|
||||
@@ -1428,6 +1425,7 @@ void Device::RemoveUnsuitableExtensions() {
|
||||
VK_KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_EXTENSION_NAME);
|
||||
|
||||
// VK_EXT_swapchain_maintenance1 (extension only, has features)
|
||||
// Requires VK_EXT_surface_maintenance1 instance extension
|
||||
extensions.swapchain_maintenance1 = features.swapchain_maintenance1.swapchainMaintenance1;
|
||||
if (extensions.swapchain_maintenance1) {
|
||||
// Check if VK_EXT_surface_maintenance1 instance extension is available
|
||||
@@ -1446,15 +1444,15 @@ void Device::RemoveUnsuitableExtensions() {
|
||||
RemoveExtensionFeatureIfUnsuitable(extensions.swapchain_maintenance1, features.swapchain_maintenance1,
|
||||
VK_EXT_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME);
|
||||
|
||||
// VK_KHR_maintenance1
|
||||
// VK_KHR_maintenance1 (core in Vulkan 1.1, no features)
|
||||
extensions.maintenance1 = loaded_extensions.contains(VK_KHR_MAINTENANCE_1_EXTENSION_NAME);
|
||||
RemoveExtensionIfUnsuitable(extensions.maintenance1, VK_KHR_MAINTENANCE_1_EXTENSION_NAME);
|
||||
|
||||
// VK_KHR_maintenance2
|
||||
// VK_KHR_maintenance2 (core in Vulkan 1.1, no features)
|
||||
extensions.maintenance2 = loaded_extensions.contains(VK_KHR_MAINTENANCE_2_EXTENSION_NAME);
|
||||
RemoveExtensionIfUnsuitable(extensions.maintenance2, VK_KHR_MAINTENANCE_2_EXTENSION_NAME);
|
||||
|
||||
// VK_KHR_maintenance3
|
||||
// VK_KHR_maintenance3 (core in Vulkan 1.1, no features)
|
||||
extensions.maintenance3 = loaded_extensions.contains(VK_KHR_MAINTENANCE_3_EXTENSION_NAME);
|
||||
RemoveExtensionIfUnsuitable(extensions.maintenance3, VK_KHR_MAINTENANCE_3_EXTENSION_NAME);
|
||||
|
||||
@@ -1484,15 +1482,15 @@ void Device::RemoveUnsuitableExtensions() {
|
||||
RemoveExtensionFeatureIfUnsuitable(extensions.maintenance6, features.maintenance6,
|
||||
VK_KHR_MAINTENANCE_6_EXTENSION_NAME);
|
||||
|
||||
// VK_KHR_maintenance7
|
||||
// VK_KHR_maintenance7 (proposed for Vulkan 1.4, no features)
|
||||
extensions.maintenance7 = loaded_extensions.contains(VK_KHR_MAINTENANCE_7_EXTENSION_NAME);
|
||||
RemoveExtensionIfUnsuitable(extensions.maintenance7, VK_KHR_MAINTENANCE_7_EXTENSION_NAME);
|
||||
|
||||
// VK_KHR_maintenance8
|
||||
// VK_KHR_maintenance8 (proposed for Vulkan 1.4, no features)
|
||||
extensions.maintenance8 = loaded_extensions.contains(VK_KHR_MAINTENANCE_8_EXTENSION_NAME);
|
||||
RemoveExtensionIfUnsuitable(extensions.maintenance8, VK_KHR_MAINTENANCE_8_EXTENSION_NAME);
|
||||
|
||||
// VK_KHR_maintenance9
|
||||
// VK_KHR_maintenance9 (proposed for Vulkan 1.4, no features)
|
||||
extensions.maintenance9 = loaded_extensions.contains(VK_KHR_MAINTENANCE_9_EXTENSION_NAME);
|
||||
RemoveExtensionIfUnsuitable(extensions.maintenance9, VK_KHR_MAINTENANCE_9_EXTENSION_NAME);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <span>
|
||||
@@ -104,9 +103,10 @@ VK_DEFINE_HANDLE(VmaAllocator)
|
||||
EXTENSION(NV, GEOMETRY_SHADER_PASSTHROUGH, geometry_shader_passthrough) \
|
||||
EXTENSION(NV, VIEWPORT_ARRAY2, viewport_array2) \
|
||||
EXTENSION(NV, VIEWPORT_SWIZZLE, viewport_swizzle) \
|
||||
EXTENSION(EXT, DESCRIPTOR_INDEXING, descriptor_indexing) \
|
||||
EXTENSION(EXT, FILTER_CUBIC, filter_cubic) \
|
||||
EXTENSION(QCOM, FILTER_CUBIC_WEIGHTS, filter_cubic_weights) \
|
||||
|
||||
EXTENSION(QCOM, FILTER_CUBIC_WEIGHTS, filter_cubic_weights)
|
||||
|
||||
// Define extensions which must be supported.
|
||||
#define FOR_EACH_VK_MANDATORY_EXTENSION(EXTENSION_NAME) \
|
||||
EXTENSION_NAME(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME) \
|
||||
@@ -440,6 +440,11 @@ public:
|
||||
return extensions.viewport_array2;
|
||||
}
|
||||
|
||||
/// Returns true if the device supporst VK_EXT_DESCRIPTOR_INDEXING
|
||||
bool isExtDescriptorIndexingSupported() const {
|
||||
return extensions.descriptor_indexing;
|
||||
}
|
||||
|
||||
/// Returns true if the device supports VK_NV_geometry_shader_passthrough.
|
||||
bool IsNvGeometryShaderPassthroughSupported() const {
|
||||
return extensions.geometry_shader_passthrough;
|
||||
@@ -548,7 +553,7 @@ public:
|
||||
return extensions.transform_feedback;
|
||||
}
|
||||
|
||||
/// Returns true if the device supports VK_EXT_transform_feedback.
|
||||
/// Returns true if the device supports VK_EXT_transform_feedback properly.
|
||||
bool AreTransformFeedbackGeometryStreamsSupported() const {
|
||||
return features.transform_feedback.geometryStreams;
|
||||
}
|
||||
@@ -598,11 +603,6 @@ public:
|
||||
return features.custom_border_color.customBorderColorWithoutFormat;
|
||||
}
|
||||
|
||||
/// Returns true if the device supports core Vulkan 1.0 dynamic states.
|
||||
bool IsCoreDynamicStateSupported() const {
|
||||
return supports_dynamic_state;
|
||||
}
|
||||
|
||||
/// Returns true if the device supports VK_EXT_extended_dynamic_state.
|
||||
bool IsExtExtendedDynamicStateSupported() const {
|
||||
return extensions.extended_dynamic_state;
|
||||
@@ -657,7 +657,7 @@ public:
|
||||
}
|
||||
|
||||
bool SupportsSmoothLines() const {
|
||||
return features.line_rasterization.smoothLines != VK_TRUE;
|
||||
return features.line_rasterization.smoothLines != VK_FALSE;
|
||||
}
|
||||
|
||||
bool SupportsStippledRectangularLines() const {
|
||||
@@ -716,11 +716,6 @@ public:
|
||||
return extensions.provoking_vertex;
|
||||
}
|
||||
|
||||
/// Returns true if provoking vertex can be used as a dynamic state.
|
||||
bool IsExtProvokingVertexDynamicStateSupported() const {
|
||||
return dynamic_state3_provoking_vertex_mode;
|
||||
}
|
||||
|
||||
/// Returns true if the device supports VK_KHR_shader_atomic_int64.
|
||||
bool IsExtShaderAtomicInt64Supported() const {
|
||||
return extensions.shader_atomic_int64;
|
||||
@@ -821,16 +816,6 @@ public:
|
||||
return properties.properties.limits.maxViewports;
|
||||
}
|
||||
|
||||
std::array<u32, 2> GetMaxViewportDimensions() const {
|
||||
return {properties.properties.limits.maxViewportDimensions[0],
|
||||
properties.properties.limits.maxViewportDimensions[1]};
|
||||
}
|
||||
|
||||
std::array<float, 2> GetViewportBoundsRange() const {
|
||||
return {properties.properties.limits.viewportBoundsRange[0],
|
||||
properties.properties.limits.viewportBoundsRange[1]};
|
||||
}
|
||||
|
||||
u32 GetMaxUserClipDistances() const {
|
||||
return properties.properties.limits.maxClipDistances;
|
||||
}
|
||||
@@ -1075,9 +1060,7 @@ private:
|
||||
bool dynamic_state3_line_stipple_enable{};
|
||||
bool dynamic_state3_alpha_to_coverage{};
|
||||
bool dynamic_state3_alpha_to_one{};
|
||||
bool dynamic_state3_provoking_vertex_mode{};
|
||||
bool supports_conditional_barriers{}; ///< Allows barriers in conditional control flow.
|
||||
bool supports_dynamic_state{true}; ///< Core Vulkan 1.0 dynamic states
|
||||
size_t sampler_heap_budget{}; ///< Sampler budget for buggy drivers (0 = unlimited).
|
||||
u64 device_access_memory{}; ///< Total size of device local memory in bytes.
|
||||
u32 sets_per_pool{}; ///< Sets per Description Pool
|
||||
|
||||
@@ -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-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||
@@ -159,7 +159,6 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept {
|
||||
X(vkCmdSetPatchControlPointsEXT);
|
||||
X(vkCmdSetLineWidth);
|
||||
X(vkCmdSetPrimitiveTopologyEXT);
|
||||
X(vkCmdSetProvokingVertexModeEXT);
|
||||
X(vkCmdSetStencilOpEXT);
|
||||
X(vkCmdSetStencilTestEnableEXT);
|
||||
X(vkCmdSetVertexInputEXT);
|
||||
|
||||
@@ -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-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||
@@ -254,7 +254,6 @@ struct DeviceDispatch : InstanceDispatch {
|
||||
PFN_vkCmdSetLogicOpEXT vkCmdSetLogicOpEXT{};
|
||||
PFN_vkCmdSetLineWidth vkCmdSetLineWidth{};
|
||||
PFN_vkCmdSetPrimitiveTopologyEXT vkCmdSetPrimitiveTopologyEXT{};
|
||||
PFN_vkCmdSetProvokingVertexModeEXT vkCmdSetProvokingVertexModeEXT{};
|
||||
PFN_vkCmdSetScissor vkCmdSetScissor{};
|
||||
PFN_vkCmdSetStencilCompareMask vkCmdSetStencilCompareMask{};
|
||||
PFN_vkCmdSetStencilOpEXT vkCmdSetStencilOpEXT{};
|
||||
@@ -1530,10 +1529,6 @@ public:
|
||||
dld->vkCmdSetPrimitiveTopologyEXT(handle, primitive_topology);
|
||||
}
|
||||
|
||||
void SetProvokingVertexEXT(VkProvokingVertexModeEXT provoking_vertex_mode) const noexcept {
|
||||
dld->vkCmdSetProvokingVertexModeEXT(handle, provoking_vertex_mode);
|
||||
}
|
||||
|
||||
void SetStencilOpEXT(VkStencilFaceFlags face_mask, VkStencilOp fail_op, VkStencilOp pass_op,
|
||||
VkStencilOp depth_fail_op, VkCompareOp compare_op) const noexcept {
|
||||
dld->vkCmdSetStencilOpEXT(handle, face_mask, fail_op, pass_op, depth_fail_op, compare_op);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||
@@ -497,7 +497,10 @@ void GameListWorker::run() {
|
||||
DirEntryReady(game_list_dir);
|
||||
AddTitlesToGameList(game_list_dir);
|
||||
} else {
|
||||
watch_list.append(QString::fromStdString(game_dir.path));
|
||||
const QString qpath = QString::fromStdString(game_dir.path);
|
||||
if (QDir(qpath).exists()) {
|
||||
watch_list.append(qpath);
|
||||
}
|
||||
auto* const game_list_dir = new GameListDir(game_dir);
|
||||
DirEntryReady(game_list_dir);
|
||||
ScanFileSystem(ScanTarget::FillManualContentProvider, game_dir.path, game_dir.deep_scan,
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// Qt on macOS doesn't define VMA shit
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
#include "qt_common/qt_string_lookup.h"
|
||||
#if defined(QT_STATICPLUGIN) && !defined(__APPLE__)
|
||||
#undef VMA_IMPLEMENTATION
|
||||
@@ -516,17 +517,8 @@ MainWindow::MainWindow(bool has_broken_vulkan)
|
||||
|
||||
#ifdef ENABLE_UPDATE_CHECKER
|
||||
if (UISettings::values.check_for_updates) {
|
||||
update_future = QtConcurrent::run([]() -> UpdateChecker::Update {
|
||||
const bool is_prerelease = ((strstr(Common::g_build_version, "pre-alpha") != NULL) ||
|
||||
(strstr(Common::g_build_version, "alpha") != NULL) ||
|
||||
(strstr(Common::g_build_version, "beta") != NULL) ||
|
||||
(strstr(Common::g_build_version, "rc") != NULL));
|
||||
const std::optional<UpdateChecker::Update> latest_release_tag =
|
||||
UpdateChecker::GetLatestRelease(is_prerelease);
|
||||
if (latest_release_tag && latest_release_tag->tag != Common::g_build_version) {
|
||||
return latest_release_tag.value();
|
||||
}
|
||||
return UpdateChecker::Update{};
|
||||
update_future = QtConcurrent::run([]() -> std::optional<UpdateChecker::Update> {
|
||||
return UpdateChecker::GetUpdate();
|
||||
});
|
||||
update_watcher.connect(&update_watcher, &QFutureWatcher<QString>::finished, this,
|
||||
&MainWindow::OnEmulatorUpdateAvailable);
|
||||
@@ -4020,8 +4012,8 @@ void MainWindow::OnCaptureScreenshot() {
|
||||
|
||||
#ifdef ENABLE_UPDATE_CHECKER
|
||||
void MainWindow::OnEmulatorUpdateAvailable() {
|
||||
UpdateChecker::Update version = update_future.result();
|
||||
if (version.tag.empty())
|
||||
std::optional<UpdateChecker::Update> version = update_future.result();
|
||||
if (!version)
|
||||
return;
|
||||
|
||||
QMessageBox update_prompt(this);
|
||||
@@ -4030,14 +4022,14 @@ void MainWindow::OnEmulatorUpdateAvailable() {
|
||||
update_prompt.addButton(QMessageBox::Yes);
|
||||
update_prompt.addButton(QMessageBox::Ignore);
|
||||
update_prompt.setText(
|
||||
tr("Download %1?").arg(QString::fromStdString(version.name)));
|
||||
tr("Download %1?").arg(QString::fromStdString(version->name)));
|
||||
update_prompt.exec();
|
||||
if (update_prompt.button(QMessageBox::Yes) == update_prompt.clickedButton()) {
|
||||
auto const full_url = fmt::format("{}/{}/releases/tag/",
|
||||
std::string{Common::g_build_auto_update_website},
|
||||
std::string{Common::g_build_auto_update_repo}
|
||||
);
|
||||
QDesktopServices::openUrl(QUrl(QString::fromStdString(full_url + version.tag)));
|
||||
QDesktopServices::openUrl(QUrl(QString::fromStdString(full_url + version->tag)));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -472,8 +472,8 @@ private:
|
||||
std::shared_ptr<InputCommon::InputSubsystem> input_subsystem;
|
||||
|
||||
#ifdef ENABLE_UPDATE_CHECKER
|
||||
QFuture<UpdateChecker::Update> update_future;
|
||||
QFutureWatcher<UpdateChecker::Update> update_watcher;
|
||||
QFuture<std::optional<UpdateChecker::Update>> update_future;
|
||||
QFutureWatcher<std::optional<UpdateChecker::Update>> update_watcher;
|
||||
#endif
|
||||
|
||||
MultiplayerState* multiplayer_state = nullptr;
|
||||
|
||||
Reference in New Issue
Block a user