mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-08-25 00:40:32 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e5ce1dc1c9 |
+1
-1
@@ -201,7 +201,7 @@
|
|||||||
"name": "openssl",
|
"name": "openssl",
|
||||||
"package": "OpenSSL",
|
"package": "OpenSSL",
|
||||||
"repo": "crueter-ci/OpenSSL",
|
"repo": "crueter-ci/OpenSSL",
|
||||||
"version": "4.0.0-11b7b6ea3b"
|
"version": "3.6.0-1cb0d36b39"
|
||||||
},
|
},
|
||||||
"openssl-cmake": {
|
"openssl-cmake": {
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
|
|||||||
-1
@@ -624,7 +624,6 @@ abstract class SettingsItem(
|
|||||||
IntSetting.FSR_SHARPENING_SLIDER,
|
IntSetting.FSR_SHARPENING_SLIDER,
|
||||||
titleId = R.string.fsr_sharpness,
|
titleId = R.string.fsr_sharpness,
|
||||||
descriptionId = R.string.fsr_sharpness_description,
|
descriptionId = R.string.fsr_sharpness_description,
|
||||||
max = 200,
|
|
||||||
units = "%"
|
units = "%"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1182,7 +1182,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|||||||
container,
|
container,
|
||||||
IntSetting.FSR_SHARPENING_SLIDER,
|
IntSetting.FSR_SHARPENING_SLIDER,
|
||||||
minValue = 0,
|
minValue = 0,
|
||||||
maxValue = 200,
|
maxValue = 100,
|
||||||
units = "%"
|
units = "%"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ object GameHelper {
|
|||||||
|
|
||||||
fun getGames(): List<Game> {
|
fun getGames(): List<Game> {
|
||||||
val games = mutableListOf<Game>()
|
val games = mutableListOf<Game>()
|
||||||
val gamesByProgramId = mutableMapOf<String, Game>()
|
|
||||||
val context = YuzuApplication.appContext
|
val context = YuzuApplication.appContext
|
||||||
preferences = PreferenceManager.getDefaultSharedPreferences(context)
|
preferences = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
|
|
||||||
@@ -64,7 +63,6 @@ object GameHelper {
|
|||||||
|
|
||||||
addGamesRecursive(
|
addGamesRecursive(
|
||||||
games,
|
games,
|
||||||
gamesByProgramId,
|
|
||||||
FileUtil.listFiles(gameDirUri),
|
FileUtil.listFiles(gameDirUri),
|
||||||
scanDepth,
|
scanDepth,
|
||||||
mountedContainerUris
|
mountedContainerUris
|
||||||
@@ -138,7 +136,6 @@ object GameHelper {
|
|||||||
|
|
||||||
private fun addGamesRecursive(
|
private fun addGamesRecursive(
|
||||||
games: MutableList<Game>,
|
games: MutableList<Game>,
|
||||||
gamesByProgramId: MutableMap<String, Game>,
|
|
||||||
files: Array<MinimalDocumentFile>,
|
files: Array<MinimalDocumentFile>,
|
||||||
depth: Int,
|
depth: Int,
|
||||||
mountedContainerUris: MutableSet<String>
|
mountedContainerUris: MutableSet<String>
|
||||||
@@ -151,7 +148,6 @@ object GameHelper {
|
|||||||
if (it.isDirectory) {
|
if (it.isDirectory) {
|
||||||
addGamesRecursive(
|
addGamesRecursive(
|
||||||
games,
|
games,
|
||||||
gamesByProgramId,
|
|
||||||
FileUtil.listFiles(it.uri),
|
FileUtil.listFiles(it.uri),
|
||||||
depth - 1,
|
depth - 1,
|
||||||
mountedContainerUris
|
mountedContainerUris
|
||||||
@@ -160,9 +156,8 @@ object GameHelper {
|
|||||||
val extension = FileUtil.getExtension(it.uri).lowercase()
|
val extension = FileUtil.getExtension(it.uri).lowercase()
|
||||||
val filePath = it.uri.toString()
|
val filePath = it.uri.toString()
|
||||||
|
|
||||||
val mountedContainer = externalContentExtensions.contains(extension) &&
|
if (externalContentExtensions.contains(extension) &&
|
||||||
mountedContainerUris.add(filePath)
|
mountedContainerUris.add(filePath)) {
|
||||||
if (mountedContainer) {
|
|
||||||
NativeLibrary.addGameFolderFileToFilesystemProvider(filePath)
|
NativeLibrary.addGameFolderFileToFilesystemProvider(filePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,20 +165,6 @@ object GameHelper {
|
|||||||
val game = getGame(it.uri, true, false)
|
val game = getGame(it.uri, true, false)
|
||||||
if (game != null) {
|
if (game != null) {
|
||||||
games.add(game)
|
games.add(game)
|
||||||
if (game.programId != "0") {
|
|
||||||
gamesByProgramId[game.programId] = game
|
|
||||||
}
|
|
||||||
} else if (mountedContainer) {
|
|
||||||
GameMetadata.getProgramId(filePath).toLongOrNull()?.let { programId ->
|
|
||||||
gamesByProgramId[(programId and 0x800L.inv()).toString()]
|
|
||||||
}?.let { existingGame ->
|
|
||||||
NativeLibrary.getPatchesForFile(existingGame.path, existingGame.programId)
|
|
||||||
existingGame.version = GameMetadata.getVersion(
|
|
||||||
existingGame.path,
|
|
||||||
true
|
|
||||||
)
|
|
||||||
GameIconUtils.refreshGameIcon(existingGame)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
@@ -27,15 +24,6 @@ import coil.request.Options
|
|||||||
import org.yuzu.yuzu_emu.R
|
import org.yuzu.yuzu_emu.R
|
||||||
import org.yuzu.yuzu_emu.YuzuApplication
|
import org.yuzu.yuzu_emu.YuzuApplication
|
||||||
import org.yuzu.yuzu_emu.model.Game
|
import org.yuzu.yuzu_emu.model.Game
|
||||||
import java.util.Collections
|
|
||||||
import java.util.WeakHashMap
|
|
||||||
|
|
||||||
private val gameIconHashes = Collections.synchronizedMap(mutableMapOf<String, Int>())
|
|
||||||
private val gameIconTargets = Collections.synchronizedMap(WeakHashMap<ImageView, GameIconTarget>())
|
|
||||||
|
|
||||||
private fun Game.iconCacheKey(): String = "$path|$version"
|
|
||||||
|
|
||||||
private data class GameIconTarget(val game: Game, var iconHash: Int? = null)
|
|
||||||
|
|
||||||
class GameIconFetcher(
|
class GameIconFetcher(
|
||||||
private val game: Game,
|
private val game: Game,
|
||||||
@@ -43,15 +31,14 @@ class GameIconFetcher(
|
|||||||
) : Fetcher {
|
) : Fetcher {
|
||||||
override suspend fun fetch(): FetchResult {
|
override suspend fun fetch(): FetchResult {
|
||||||
return DrawableResult(
|
return DrawableResult(
|
||||||
drawable = decodeGameIcon(game)!!.toDrawable(options.context.resources),
|
drawable = decodeGameIcon(game.path)!!.toDrawable(options.context.resources),
|
||||||
isSampled = false,
|
isSampled = false,
|
||||||
dataSource = DataSource.DISK
|
dataSource = DataSource.DISK
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun decodeGameIcon(game: Game): Bitmap? {
|
private fun decodeGameIcon(uri: String): Bitmap? {
|
||||||
val data = GameMetadata.getIcon(game.path)
|
val data = GameMetadata.getIcon(uri)
|
||||||
gameIconHashes[game.iconCacheKey()] = data.contentHashCode()
|
|
||||||
return BitmapFactory.decodeByteArray(
|
return BitmapFactory.decodeByteArray(
|
||||||
data,
|
data,
|
||||||
0,
|
0,
|
||||||
@@ -67,7 +54,7 @@ class GameIconFetcher(
|
|||||||
}
|
}
|
||||||
|
|
||||||
class GameIconKeyer : Keyer<Game> {
|
class GameIconKeyer : Keyer<Game> {
|
||||||
override fun key(data: Game, options: Options): String = data.iconCacheKey()
|
override fun key(data: Game, options: Options): String = data.path
|
||||||
}
|
}
|
||||||
|
|
||||||
object GameIconUtils {
|
object GameIconUtils {
|
||||||
@@ -84,58 +71,14 @@ object GameIconUtils {
|
|||||||
.build()
|
.build()
|
||||||
|
|
||||||
fun loadGameIcon(game: Game, imageView: ImageView) {
|
fun loadGameIcon(game: Game, imageView: ImageView) {
|
||||||
gameIconTargets[imageView] = GameIconTarget(game)
|
|
||||||
val request = ImageRequest.Builder(YuzuApplication.appContext)
|
val request = ImageRequest.Builder(YuzuApplication.appContext)
|
||||||
.data(game)
|
.data(game)
|
||||||
.target(imageView)
|
.target(imageView)
|
||||||
.error(R.drawable.default_icon)
|
.error(R.drawable.default_icon)
|
||||||
.listener(
|
|
||||||
onSuccess = { _, _ ->
|
|
||||||
val target = gameIconTargets[imageView]
|
|
||||||
if (target?.game?.iconCacheKey() == game.iconCacheKey()) {
|
|
||||||
gameIconHashes[game.iconCacheKey()]?.let {
|
|
||||||
target.iconHash = it
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onError = { _, _ ->
|
|
||||||
gameIconTargets[imageView]?.iconHash = null
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.build()
|
.build()
|
||||||
imageLoader.enqueue(request)
|
imageLoader.enqueue(request)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun refreshGameIcon(game: Game) {
|
|
||||||
val targets = synchronized(gameIconTargets) {
|
|
||||||
gameIconTargets
|
|
||||||
.filterValues { it.game.path == game.path && it.game.programId == game.programId }
|
|
||||||
.keys
|
|
||||||
.toList()
|
|
||||||
}
|
|
||||||
if (targets.isEmpty()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val iconHash = GameMetadata.getIcon(game.path).contentHashCode()
|
|
||||||
val targetsToRefresh = targets.filter { gameIconTargets[it]?.iconHash != iconHash }
|
|
||||||
if (targetsToRefresh.isEmpty()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
imageLoader.memoryCache?.remove(MemoryCache.Key(game.iconCacheKey()))
|
|
||||||
targetsToRefresh.forEach { imageView ->
|
|
||||||
imageView.post {
|
|
||||||
val target = gameIconTargets[imageView] ?: return@post
|
|
||||||
if (target.game.path == game.path && target.game.programId == game.programId) {
|
|
||||||
if (target.iconHash != iconHash) {
|
|
||||||
loadGameIcon(game, imageView)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun getGameIcon(lifecycleOwner: LifecycleOwner, game: Game): Bitmap {
|
suspend fun getGameIcon(lifecycleOwner: LifecycleOwner, game: Game): Bitmap {
|
||||||
val request = ImageRequest.Builder(YuzuApplication.appContext)
|
val request = ImageRequest.Builder(YuzuApplication.appContext)
|
||||||
.data(game)
|
.data(game)
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<item android:state_pressed="true" android:color="?attr/colorControlHighlight" />
|
|
||||||
<item android:state_focused="true" android:color="@android:color/transparent" />
|
|
||||||
<item android:state_selected="true" android:color="@android:color/transparent" />
|
|
||||||
<item android:state_hovered="true" android:color="@android:color/transparent" />
|
|
||||||
<item android:color="@android:color/transparent" />
|
|
||||||
</selector>
|
|
||||||
@@ -10,7 +10,6 @@
|
|||||||
android:clipChildren="true"
|
android:clipChildren="true"
|
||||||
android:layout_margin="0dp"
|
android:layout_margin="0dp"
|
||||||
app:cardBackgroundColor="@color/eden_card_background"
|
app:cardBackgroundColor="@color/eden_card_background"
|
||||||
app:rippleColor="@color/game_card_ripple"
|
|
||||||
app:strokeWidth="1dp"
|
app:strokeWidth="1dp"
|
||||||
app:strokeColor="@color/eden_border">
|
app:strokeColor="@color/eden_border">
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,6 @@
|
|||||||
app:cardCornerRadius="16dp"
|
app:cardCornerRadius="16dp"
|
||||||
app:cardPreventCornerOverlap="true"
|
app:cardPreventCornerOverlap="true"
|
||||||
android:clipChildren="true"
|
android:clipChildren="true"
|
||||||
app:rippleColor="@color/game_card_ripple"
|
|
||||||
android:layout_margin="4dp">
|
android:layout_margin="4dp">
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
|||||||
@@ -22,7 +22,6 @@
|
|||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:transitionName="card_game"
|
android:transitionName="card_game"
|
||||||
app:cardCornerRadius="16dp"
|
app:cardCornerRadius="16dp"
|
||||||
app:rippleColor="@color/game_card_ripple"
|
|
||||||
android:foreground="@color/eden_border_gradient_start">
|
android:foreground="@color/eden_border_gradient_start">
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
|||||||
@@ -22,7 +22,6 @@
|
|||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:transitionName="card_game_compact"
|
android:transitionName="card_game_compact"
|
||||||
app:cardCornerRadius="16dp"
|
app:cardCornerRadius="16dp"
|
||||||
app:rippleColor="@color/game_card_ripple"
|
|
||||||
android:foreground="@color/eden_border_gradient_start">
|
android:foreground="@color/eden_border_gradient_start">
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
app:cardCornerRadius="16dp"
|
app:cardCornerRadius="16dp"
|
||||||
app:cardElevation="0dp"
|
app:cardElevation="0dp"
|
||||||
app:cardBackgroundColor="@android:color/transparent"
|
app:cardBackgroundColor="@android:color/transparent"
|
||||||
app:rippleColor="@color/game_card_ripple"
|
|
||||||
app:strokeWidth="0dp">
|
app:strokeWidth="0dp">
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
|||||||
@@ -1107,6 +1107,7 @@
|
|||||||
<string name="theme_mode_light">فاتح</string>
|
<string name="theme_mode_light">فاتح</string>
|
||||||
<string name="theme_mode_dark">داكن</string>
|
<string name="theme_mode_dark">داكن</string>
|
||||||
|
|
||||||
|
<string name="multiplier_none">لا شيء</string>
|
||||||
|
|
||||||
<!-- Black backgrounds theme -->
|
<!-- Black backgrounds theme -->
|
||||||
<string name="use_black_backgrounds">خلفيات سوداء</string>
|
<string name="use_black_backgrounds">خلفيات سوداء</string>
|
||||||
|
|||||||
@@ -991,6 +991,7 @@ Wirklich fortfahren?</string>
|
|||||||
<string name="theme_mode_light">Hell</string>
|
<string name="theme_mode_light">Hell</string>
|
||||||
<string name="theme_mode_dark">Dunkel</string>
|
<string name="theme_mode_dark">Dunkel</string>
|
||||||
|
|
||||||
|
<string name="multiplier_none">Keine</string>
|
||||||
|
|
||||||
<!-- Black backgrounds theme -->
|
<!-- Black backgrounds theme -->
|
||||||
<string name="use_black_backgrounds">Schwarze Hintergründe</string>
|
<string name="use_black_backgrounds">Schwarze Hintergründe</string>
|
||||||
|
|||||||
@@ -1092,6 +1092,7 @@
|
|||||||
<string name="theme_mode_light">Claro</string>
|
<string name="theme_mode_light">Claro</string>
|
||||||
<string name="theme_mode_dark">Oscuro</string>
|
<string name="theme_mode_dark">Oscuro</string>
|
||||||
|
|
||||||
|
<string name="multiplier_none">Nada</string>
|
||||||
|
|
||||||
<!-- Black backgrounds theme -->
|
<!-- Black backgrounds theme -->
|
||||||
<string name="use_black_backgrounds">Fondos oscuros</string>
|
<string name="use_black_backgrounds">Fondos oscuros</string>
|
||||||
|
|||||||
@@ -808,6 +808,9 @@
|
|||||||
<string name="multiplier_x4">x4</string>
|
<string name="multiplier_x4">x4</string>
|
||||||
<string name="multiplier_x8">x8</string>
|
<string name="multiplier_x8">x8</string>
|
||||||
<string name="multiplier_x16">x16</string>
|
<string name="multiplier_x16">x16</string>
|
||||||
|
<string name="multiplier_x32">x32</string>
|
||||||
|
<string name="multiplier_x64">x64</string>
|
||||||
|
<string name="multiplier_none">None</string>
|
||||||
|
|
||||||
<!-- Black backgrounds theme -->
|
<!-- Black backgrounds theme -->
|
||||||
<string name="use_black_backgrounds">پسزمینه مشکی</string>
|
<string name="use_black_backgrounds">پسزمینه مشکی</string>
|
||||||
|
|||||||
@@ -1004,6 +1004,7 @@
|
|||||||
<string name="theme_mode_light">Lumineux</string>
|
<string name="theme_mode_light">Lumineux</string>
|
||||||
<string name="theme_mode_dark">Sombre</string>
|
<string name="theme_mode_dark">Sombre</string>
|
||||||
|
|
||||||
|
<string name="multiplier_none">Aucun</string>
|
||||||
|
|
||||||
<!-- Black backgrounds theme -->
|
<!-- Black backgrounds theme -->
|
||||||
<string name="use_black_backgrounds">Arrière-plan noir</string>
|
<string name="use_black_backgrounds">Arrière-plan noir</string>
|
||||||
|
|||||||
@@ -935,6 +935,7 @@
|
|||||||
<string name="theme_mode_light">Jasny</string>
|
<string name="theme_mode_light">Jasny</string>
|
||||||
<string name="theme_mode_dark">Ciemny</string>
|
<string name="theme_mode_dark">Ciemny</string>
|
||||||
|
|
||||||
|
<string name="multiplier_none">Brak</string>
|
||||||
|
|
||||||
<!-- Black backgrounds theme -->
|
<!-- Black backgrounds theme -->
|
||||||
<string name="use_black_backgrounds">Czarne tła</string>
|
<string name="use_black_backgrounds">Czarne tła</string>
|
||||||
|
|||||||
@@ -891,6 +891,7 @@
|
|||||||
<string name="theme_mode_light">Claro</string>
|
<string name="theme_mode_light">Claro</string>
|
||||||
<string name="theme_mode_dark">Escuro</string>
|
<string name="theme_mode_dark">Escuro</string>
|
||||||
|
|
||||||
|
<string name="multiplier_none">Nenhum</string>
|
||||||
|
|
||||||
<!-- Black backgrounds theme -->
|
<!-- Black backgrounds theme -->
|
||||||
<string name="use_black_backgrounds">Planos de fundo pretos</string>
|
<string name="use_black_backgrounds">Planos de fundo pretos</string>
|
||||||
|
|||||||
@@ -1071,6 +1071,7 @@
|
|||||||
<string name="theme_mode_light">Светлая</string>
|
<string name="theme_mode_light">Светлая</string>
|
||||||
<string name="theme_mode_dark">Темная</string>
|
<string name="theme_mode_dark">Темная</string>
|
||||||
|
|
||||||
|
<string name="multiplier_none">Отключено</string>
|
||||||
|
|
||||||
<!-- Black backgrounds theme -->
|
<!-- Black backgrounds theme -->
|
||||||
<string name="use_black_backgrounds">Чёрный фон</string>
|
<string name="use_black_backgrounds">Чёрный фон</string>
|
||||||
|
|||||||
@@ -1053,6 +1053,7 @@
|
|||||||
<string name="theme_mode_light">Світла</string>
|
<string name="theme_mode_light">Світла</string>
|
||||||
<string name="theme_mode_dark">Темна</string>
|
<string name="theme_mode_dark">Темна</string>
|
||||||
|
|
||||||
|
<string name="multiplier_none">Жодного</string>
|
||||||
|
|
||||||
<!-- Black backgrounds theme -->
|
<!-- Black backgrounds theme -->
|
||||||
<string name="use_black_backgrounds">Чорний фон</string>
|
<string name="use_black_backgrounds">Чорний фон</string>
|
||||||
|
|||||||
@@ -1081,6 +1081,7 @@
|
|||||||
<string name="theme_mode_light">浅色</string>
|
<string name="theme_mode_light">浅色</string>
|
||||||
<string name="theme_mode_dark">深色</string>
|
<string name="theme_mode_dark">深色</string>
|
||||||
|
|
||||||
|
<string name="multiplier_none">无</string>
|
||||||
|
|
||||||
<!-- Black backgrounds theme -->
|
<!-- Black backgrounds theme -->
|
||||||
<string name="use_black_backgrounds">使用黑色背景</string>
|
<string name="use_black_backgrounds">使用黑色背景</string>
|
||||||
|
|||||||
@@ -1006,6 +1006,7 @@
|
|||||||
<string name="theme_mode_light">淺色</string>
|
<string name="theme_mode_light">淺色</string>
|
||||||
<string name="theme_mode_dark">深色</string>
|
<string name="theme_mode_dark">深色</string>
|
||||||
|
|
||||||
|
<string name="multiplier_none">無</string>
|
||||||
|
|
||||||
<!-- Black backgrounds theme -->
|
<!-- Black backgrounds theme -->
|
||||||
<string name="use_black_backgrounds">黑色背景</string>
|
<string name="use_black_backgrounds">黑色背景</string>
|
||||||
|
|||||||
@@ -111,38 +111,43 @@
|
|||||||
<item>1</item>
|
<item>1</item>
|
||||||
</integer-array>
|
</integer-array>
|
||||||
|
|
||||||
|
<!-- VRAM USAGE MODE CHOICES -->
|
||||||
<string-array name="vramUsageMethodNames">
|
<string-array name="vramUsageMethodNames">
|
||||||
<item>@string/vram_usage_conservative</item>
|
<item>@string/vram_usage_conservative</item>
|
||||||
<item>@string/vram_usage_aggressive</item>
|
<item>@string/vram_usage_aggressive</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
<!-- VRAM USAGE MODE VALUES -->
|
||||||
<integer-array name="vramUsageMethodValues">
|
<integer-array name="vramUsageMethodValues">
|
||||||
<item>0</item>
|
<item>0</item> <!-- Conservative -->
|
||||||
<item>1</item>
|
<item>1</item> <!-- Aggressive -->
|
||||||
</integer-array>
|
</integer-array>
|
||||||
|
|
||||||
|
<!-- ASTC Decoding Method Choices -->
|
||||||
<string-array name="astcDecodingMethodNames">
|
<string-array name="astcDecodingMethodNames">
|
||||||
<item>@string/accelerate_astc_cpu</item>
|
<item>@string/accelerate_astc_cpu</item>
|
||||||
<item>@string/accelerate_astc_gpu</item>
|
<item>@string/accelerate_astc_gpu</item>
|
||||||
<item>@string/accelerate_astc_async</item>
|
<item>@string/accelerate_astc_async</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
<!-- ASTC Decoding Method Values -->
|
||||||
<integer-array name="astcDecodingMethodValues">
|
<integer-array name="astcDecodingMethodValues">
|
||||||
<item>0</item>
|
<item>0</item> <!-- CPU -->
|
||||||
<item>1</item>
|
<item>1</item> <!-- GPU -->
|
||||||
<item>2</item>
|
<item>2</item> <!-- CPU Asynchronously -->
|
||||||
</integer-array>
|
</integer-array>
|
||||||
|
<!-- NVDEC Emulation Choices -->
|
||||||
<string-array name="rendererNvdecNames">
|
<string-array name="rendererNvdecNames">
|
||||||
<item>@string/nvdec_emulation_none</item>
|
<item>@string/nvdec_emulation_none</item> <!-- Off -->
|
||||||
<item>@string/nvdec_emulation_cpu</item>
|
<item>@string/nvdec_emulation_cpu</item> <!-- Cpu -->
|
||||||
<item>@string/nvdec_emulation_gpu</item>
|
<item>@string/nvdec_emulation_gpu</item> <!-- Gpu -->
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
<!-- NVDEC Emulation Values -->
|
||||||
<integer-array name="rendererNvdecValues">
|
<integer-array name="rendererNvdecValues">
|
||||||
<item>0</item>
|
<item>3</item> <!-- Off value -->
|
||||||
<item>1</item>
|
<item>1</item> <!-- CPU value -->
|
||||||
<item>2</item>
|
<item>2</item> <!-- GPU value -->
|
||||||
</integer-array>
|
</integer-array>
|
||||||
|
|
||||||
<string-array name="rendererResolutionNames">
|
<string-array name="rendererResolutionNames">
|
||||||
@@ -508,6 +513,9 @@
|
|||||||
<item>@string/multiplier_x4</item>
|
<item>@string/multiplier_x4</item>
|
||||||
<item>@string/multiplier_x8</item>
|
<item>@string/multiplier_x8</item>
|
||||||
<item>@string/multiplier_x16</item>
|
<item>@string/multiplier_x16</item>
|
||||||
|
<item>@string/multiplier_x32</item>
|
||||||
|
<item>@string/multiplier_x64</item>
|
||||||
|
<item>@string/multiplier_none</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<integer-array name="anisoValues">
|
<integer-array name="anisoValues">
|
||||||
<item>0</item>
|
<item>0</item>
|
||||||
@@ -516,6 +524,9 @@
|
|||||||
<item>3</item>
|
<item>3</item>
|
||||||
<item>4</item>
|
<item>4</item>
|
||||||
<item>5</item>
|
<item>5</item>
|
||||||
|
<item>6</item>
|
||||||
|
<item>7</item>
|
||||||
|
<item>8</item>
|
||||||
</integer-array>
|
</integer-array>
|
||||||
|
|
||||||
<string-array name="verticalAlignmentEntries">
|
<string-array name="verticalAlignmentEntries">
|
||||||
|
|||||||
@@ -1246,6 +1246,9 @@
|
|||||||
<string name="multiplier_x4" translatable="false">x4</string>
|
<string name="multiplier_x4" translatable="false">x4</string>
|
||||||
<string name="multiplier_x8" translatable="false">x8</string>
|
<string name="multiplier_x8" translatable="false">x8</string>
|
||||||
<string name="multiplier_x16" translatable="false">x16</string>
|
<string name="multiplier_x16" translatable="false">x16</string>
|
||||||
|
<string name="multiplier_x32" translatable="false">x32</string>
|
||||||
|
<string name="multiplier_x64" translatable="false">x64</string>
|
||||||
|
<string name="multiplier_none">None</string>
|
||||||
|
|
||||||
<!-- Black backgrounds theme -->
|
<!-- Black backgrounds theme -->
|
||||||
<string name="use_black_backgrounds">Black backgrounds</string>
|
<string name="use_black_backgrounds">Black backgrounds</string>
|
||||||
|
|||||||
+45
-56
@@ -39,19 +39,6 @@
|
|||||||
|
|
||||||
namespace Common::Log {
|
namespace Common::Log {
|
||||||
|
|
||||||
/// @brief A log entry. Log entries are store in a structured format to permit more varied output
|
|
||||||
/// formatting on different frontends, as well as facilitating filtering and aggregation.
|
|
||||||
struct Entry {
|
|
||||||
char const* message = nullptr;
|
|
||||||
size_t message_len = 0;
|
|
||||||
std::chrono::microseconds timestamp;
|
|
||||||
Class log_class{};
|
|
||||||
Level log_level{};
|
|
||||||
const char* filename = nullptr;
|
|
||||||
const char* function = nullptr;
|
|
||||||
uint32_t line_num = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
/// @brief Returns the name of the passed log class as a C-string. Subclasses are separated by periods
|
/// @brief Returns the name of the passed log class as a C-string. Subclasses are separated by periods
|
||||||
@@ -83,6 +70,8 @@ const char* GetLevelName(Level log_level) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// Some IDEs prefer <file>:<line> instead, so let's just do that :)
|
// Some IDEs prefer <file>:<line> instead, so let's just do that :)
|
||||||
std::string FormatLogMessage(const Entry& entry) noexcept {
|
std::string FormatLogMessage(const Entry& entry) noexcept {
|
||||||
if (!entry.filename) return "";
|
if (!entry.filename) return "";
|
||||||
@@ -90,9 +79,10 @@ std::string FormatLogMessage(const Entry& entry) noexcept {
|
|||||||
auto const time_fractional = uint32_t(entry.timestamp.count() % 1000000);
|
auto const time_fractional = uint32_t(entry.timestamp.count() % 1000000);
|
||||||
auto const class_name = GetLogClassName(entry.log_class);
|
auto const class_name = GetLogClassName(entry.log_class);
|
||||||
auto const level_name = GetLevelName(entry.log_level);
|
auto const level_name = GetLevelName(entry.log_level);
|
||||||
return fmt::format("[{:4d}.{:06d}] {} <{}> {}:{}:{}: {}\n", time_seconds, time_fractional, class_name, level_name, entry.filename, entry.line_num, entry.function, entry.message);
|
return fmt::format("[{:4d}.{:06d}] {} <{}> {}:{}:{}: {}", time_seconds, time_fractional, class_name, level_name, entry.filename, entry.line_num, entry.function, entry.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
template <typename It>
|
template <typename It>
|
||||||
Level GetLevelByName(const It begin, const It end) {
|
Level GetLevelByName(const It begin, const It end) {
|
||||||
for (u32 i = 0; i < u32(Level::Count); ++i) {
|
for (u32 i = 0; i < u32(Level::Count); ++i) {
|
||||||
@@ -137,6 +127,25 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
|
|||||||
instance.SetClassLevel(log_class, level);
|
instance.SetClassLevel(log_class, level);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
} // Anonymous namespace
|
||||||
|
|
||||||
|
void Filter::ParseFilterString(std::string_view filter_view) {
|
||||||
|
auto clause_begin = filter_view.cbegin();
|
||||||
|
while (clause_begin != filter_view.cend()) {
|
||||||
|
auto clause_end = std::find(clause_begin, filter_view.cend(), ' ');
|
||||||
|
// If clause isn't empty
|
||||||
|
if (clause_end != clause_begin) {
|
||||||
|
ParseFilterRule(*this, clause_begin, clause_end);
|
||||||
|
}
|
||||||
|
if (clause_end != filter_view.cend()) {
|
||||||
|
// Skip over the whitespace
|
||||||
|
++clause_end;
|
||||||
|
}
|
||||||
|
clause_begin = clause_end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
/// @brief Trims up to and including the last of ../, ..\, src/, src\ in a string
|
/// @brief Trims up to and including the last of ../, ..\, src/, src\ in a string
|
||||||
/// do not be fooled this isn't generating new strings on .rodata :)
|
/// do not be fooled this isn't generating new strings on .rodata :)
|
||||||
@@ -199,7 +208,7 @@ struct ColorConsoleBackend final : public Backend {
|
|||||||
}());
|
}());
|
||||||
SetConsoleTextAttribute(console_handle, color);
|
SetConsoleTextAttribute(console_handle, color);
|
||||||
auto const df = GetDirectFormatArgs(entry);
|
auto const df = GetDirectFormatArgs(entry);
|
||||||
std::fprintf(stdout, CCB_PRINTF_FMT "\n", df.time_seconds, df.time_fractional, df.class_name, df.level_name, entry.filename, entry.line_num, entry.function, entry.message);
|
std::fprintf(stdout, CCB_PRINTF_FMT "\n", df.time_seconds, df.time_fractional, df.class_name, df.level_name, entry.filename, entry.line_num, entry.function, entry.message.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void Flush() noexcept override {}
|
void Flush() noexcept override {}
|
||||||
@@ -211,24 +220,22 @@ struct ColorConsoleBackend final : public Backend {
|
|||||||
~ColorConsoleBackend() noexcept override {}
|
~ColorConsoleBackend() noexcept override {}
|
||||||
void Write(const Entry& entry) noexcept override {
|
void Write(const Entry& entry) noexcept override {
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
|
#define ESC "\x1b"
|
||||||
auto const color_str = [&entry]() -> const char* {
|
auto const color_str = [&entry]() -> const char* {
|
||||||
switch (entry.log_level) {
|
switch (entry.log_level) {
|
||||||
case Level::Debug: return "[0;36m"; // Cyan
|
#define CCB_MAKE_COLOR_FMT(X) ESC X CCB_PRINTF_FMT ESC "[0m\n"
|
||||||
case Level::Info: return "[0;37m"; // Bright gray
|
case Level::Debug: return CCB_MAKE_COLOR_FMT("[0;36m"); // Cyan
|
||||||
case Level::Warning: return "[1;33m"; // Bright yellow
|
case Level::Info: return CCB_MAKE_COLOR_FMT("[0;37m"); // Bright gray
|
||||||
case Level::Error: return "[1;31m"; // Bright red
|
case Level::Warning: return CCB_MAKE_COLOR_FMT("[1;33m"); // Bright yellow
|
||||||
case Level::Critical: return "[1;35m"; // Bright magenta
|
case Level::Error: return CCB_MAKE_COLOR_FMT("[1;31m"); // Bright red
|
||||||
default: return "[1;30m"; // Grey
|
case Level::Critical: return CCB_MAKE_COLOR_FMT("[1;35m"); // Bright magenta
|
||||||
|
default: return CCB_MAKE_COLOR_FMT("[1;30m"); // Grey
|
||||||
|
#undef CCB_MAKE_COLOR_FMT
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
auto const df = GetDirectFormatArgs(entry);
|
auto const df = GetDirectFormatArgs(entry);
|
||||||
// more restrictive, because take for example this simple prelude:
|
std::fprintf(stdout, color_str, df.time_seconds, df.time_fractional, df.class_name, df.level_name, entry.filename, entry.line_num, entry.function, entry.message.c_str());
|
||||||
// [ 50.872256] Config <Info> common/settings.cpp:142:LogSettings:
|
#undef ESC
|
||||||
char buffer[128];
|
|
||||||
auto result = fmt::format_to_n(buffer, sizeof(buffer) - 1, "\x1b{}[{:4d}.{:06d}] {} <{}> {}:{}:{}: ", color_str, df.time_seconds, df.time_fractional, df.class_name, df.level_name, entry.filename, entry.line_num, entry.function, entry.message);
|
|
||||||
std::fwrite(buffer, 1, (std::min)(sizeof(buffer) - 1, result.size), stdout);
|
|
||||||
std::fwrite(entry.message, 1, entry.message_len, stdout);
|
|
||||||
std::fwrite("\x1b[0m\n", 1, sizeof("\x1b[0m\n"), stdout);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void Flush() noexcept override {}
|
void Flush() noexcept override {}
|
||||||
@@ -239,7 +246,7 @@ struct ColorConsoleBackend final : public Backend {
|
|||||||
#ifndef __OPENORBIS__
|
#ifndef __OPENORBIS__
|
||||||
/// @brief Backend that writes to a file passed into the constructor
|
/// @brief Backend that writes to a file passed into the constructor
|
||||||
struct FileBackend final : public Backend {
|
struct FileBackend final : public Backend {
|
||||||
explicit FileBackend(const std::filesystem::path filename) noexcept {
|
explicit FileBackend(const std::filesystem::path& filename) noexcept {
|
||||||
auto old_filename = filename;
|
auto old_filename = filename;
|
||||||
old_filename += ".old.txt";
|
old_filename += ".old.txt";
|
||||||
// Existence checks are done within the functions themselves.
|
// Existence checks are done within the functions themselves.
|
||||||
@@ -254,7 +261,7 @@ struct FileBackend final : public Backend {
|
|||||||
if (!enabled)
|
if (!enabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto message = FormatLogMessage(entry);
|
auto message = FormatLogMessage(entry).append(1, '\n');
|
||||||
#ifndef __ANDROID__
|
#ifndef __ANDROID__
|
||||||
if (Settings::values.censor_username.GetValue()) {
|
if (Settings::values.censor_username.GetValue()) {
|
||||||
// This must be a static otherwise it would get checked on EVERY
|
// This must be a static otherwise it would get checked on EVERY
|
||||||
@@ -262,7 +269,8 @@ struct FileBackend final : public Backend {
|
|||||||
static std::string username = []() -> std::string {
|
static std::string username = []() -> std::string {
|
||||||
// in order of precedence
|
// in order of precedence
|
||||||
// LOGNAME usually works on UNIX, USERNAME on Windows
|
// LOGNAME usually works on UNIX, USERNAME on Windows
|
||||||
// Some UNIX systems suck and don't use LOGNAME so we also need USER :(
|
// Some UNIX systems suck and don't use LOGNAME so we also
|
||||||
|
// need USER :(
|
||||||
for (auto const var : { "LOGNAME", "USERNAME", "USER", })
|
for (auto const var : { "LOGNAME", "USERNAME", "USER", })
|
||||||
if (auto const s = ::getenv(var); s != nullptr)
|
if (auto const s = ::getenv(var); s != nullptr)
|
||||||
return std::string{s};
|
return std::string{s};
|
||||||
@@ -272,7 +280,7 @@ struct FileBackend final : public Backend {
|
|||||||
boost::replace_all(message, username, "user");
|
boost::replace_all(message, username, "user");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
bytes_written += file->WriteSpan(std::span<const char>{message.begin(), message.end()});
|
bytes_written += file->WriteString(message);
|
||||||
|
|
||||||
// Option to log each line rather than 4k buffers
|
// Option to log each line rather than 4k buffers
|
||||||
if (Settings::values.log_flush_line.GetValue())
|
if (Settings::values.log_flush_line.GetValue())
|
||||||
@@ -300,13 +308,14 @@ private:
|
|||||||
bool enabled = true;
|
bool enabled = true;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
/// @brief Backend that writes to Visual Studio's output window
|
/// @brief Backend that writes to Visual Studio's output window
|
||||||
struct DebuggerBackend final : public Backend {
|
struct DebuggerBackend final : public Backend {
|
||||||
explicit DebuggerBackend() noexcept = default;
|
explicit DebuggerBackend() noexcept = default;
|
||||||
~DebuggerBackend() noexcept override = default;
|
~DebuggerBackend() noexcept override = default;
|
||||||
void Write(const Entry& entry) noexcept override {
|
void Write(const Entry& entry) noexcept override {
|
||||||
::OutputDebugStringW(UTF8ToUTF16W(FormatLogMessage(entry)).c_str());
|
::OutputDebugStringW(UTF8ToUTF16W(FormatLogMessage(entry).append(1, '\n')).c_str());
|
||||||
}
|
}
|
||||||
void Flush() noexcept override {}
|
void Flush() noexcept override {}
|
||||||
};
|
};
|
||||||
@@ -329,7 +338,7 @@ struct LogcatBackend : public Backend {
|
|||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
auto const df = GetDirectFormatArgs(entry);
|
auto const df = GetDirectFormatArgs(entry);
|
||||||
__android_log_print(android_log_priority, "YuzuNative", CCB_PRINTF_FMT, df.time_seconds, df.time_fractional, df.class_name, df.level_name, entry.filename, entry.line_num, entry.function, entry.message);
|
__android_log_print(android_log_priority, "YuzuNative", CCB_PRINTF_FMT, df.time_seconds, df.time_fractional, df.class_name, df.level_name, entry.filename, entry.line_num, entry.function, entry.message.c_str());
|
||||||
}
|
}
|
||||||
void Flush() noexcept override {}
|
void Flush() noexcept override {}
|
||||||
};
|
};
|
||||||
@@ -368,23 +377,7 @@ struct Impl {
|
|||||||
#endif
|
#endif
|
||||||
std::chrono::steady_clock::time_point time_origin{std::chrono::steady_clock::now()};
|
std::chrono::steady_clock::time_point time_origin{std::chrono::steady_clock::now()};
|
||||||
};
|
};
|
||||||
} // Anonymous namespace
|
} // namespace
|
||||||
|
|
||||||
void Filter::ParseFilterString(std::string_view filter_view) {
|
|
||||||
auto clause_begin = filter_view.cbegin();
|
|
||||||
while (clause_begin < filter_view.cend()) {
|
|
||||||
auto clause_end = std::find(clause_begin, filter_view.cend(), ' ');
|
|
||||||
// If clause isn't empty
|
|
||||||
if (clause_end != clause_begin) {
|
|
||||||
ParseFilterRule(*this, clause_begin, clause_end);
|
|
||||||
}
|
|
||||||
if (clause_end != filter_view.cend()) {
|
|
||||||
// Skip over the whitespace
|
|
||||||
++clause_end;
|
|
||||||
}
|
|
||||||
clause_begin = clause_end;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Constructor shall NOT depend upon Settings() or whatever
|
// Constructor shall NOT depend upon Settings() or whatever
|
||||||
// it's ran at global static ctor() time... so BE CAREFUL MFER!
|
// it's ran at global static ctor() time... so BE CAREFUL MFER!
|
||||||
@@ -425,14 +418,10 @@ void SetColorConsoleBackendEnabled(bool enabled) {
|
|||||||
|
|
||||||
void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename, unsigned int line_num, const char* function, fmt::string_view format, const fmt::format_args& args) {
|
void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename, unsigned int line_num, const char* function, fmt::string_view format, const fmt::format_args& args) {
|
||||||
if (logging_instance && logging_instance->filter.CheckMessage(log_class, log_level)) {
|
if (logging_instance && logging_instance->filter.CheckMessage(log_class, log_level)) {
|
||||||
char buffer[BUFSIZ];
|
|
||||||
auto result = fmt::vformat_to_n(buffer, sizeof(buffer) - 1, format, args);
|
|
||||||
buffer[result.size] = '\0';
|
|
||||||
auto const flush = ::Settings::values.log_flush_line.GetValue();
|
auto const flush = ::Settings::values.log_flush_line.GetValue();
|
||||||
logging_instance->ForEachBackend([=](Backend& backend) {
|
logging_instance->ForEachBackend([=](Backend& backend) {
|
||||||
backend.Write(Entry{
|
backend.Write(Entry{
|
||||||
.message = buffer,
|
.message = fmt::vformat(format, args),
|
||||||
.message_len = (std::min)(sizeof(buffer) - 1, result.size),
|
|
||||||
.timestamp = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - logging_instance->time_origin),
|
.timestamp = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - logging_instance->time_origin),
|
||||||
.log_class = log_class,
|
.log_class = log_class,
|
||||||
.log_level = log_level,
|
.log_level = log_level,
|
||||||
|
|||||||
@@ -140,4 +140,25 @@ void Stop();
|
|||||||
void SetGlobalFilter(const Filter& filter);
|
void SetGlobalFilter(const Filter& filter);
|
||||||
void SetColorConsoleBackendEnabled(bool enabled);
|
void SetColorConsoleBackendEnabled(bool enabled);
|
||||||
|
|
||||||
|
/// @brief A log entry. Log entries are store in a structured format to permit more varied output
|
||||||
|
/// formatting on different frontends, as well as facilitating filtering and aggregation.
|
||||||
|
struct Entry {
|
||||||
|
std::string message;
|
||||||
|
std::chrono::microseconds timestamp;
|
||||||
|
Class log_class{};
|
||||||
|
Level log_level{};
|
||||||
|
const char* filename = nullptr;
|
||||||
|
const char* function = nullptr;
|
||||||
|
unsigned int line_num = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Formats a log entry into the provided text buffer.
|
||||||
|
std::string FormatLogMessage(const Entry& entry) noexcept;
|
||||||
|
|
||||||
|
/// Prints the same message as `PrintMessage`, but colored according to the severity level.
|
||||||
|
void PrintColoredMessage(const Entry& entry) noexcept;
|
||||||
|
|
||||||
|
/// Formats and prints a log entry to the android logcat.
|
||||||
|
void PrintMessageToLogcat(const Entry& entry) noexcept;
|
||||||
|
|
||||||
} // namespace Common::Log
|
} // namespace Common::Log
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ ENUM(TimeZone, Auto, Default, Cet, Cst6Cdt, Cuba, Eet, Egypt, Eire, Est, Est5Edt
|
|||||||
GmtPlusZero, GmtMinusZero, GmtZero, Greenwich, Hongkong, Hst, Iceland, Iran, Israel, Jamaica,
|
GmtPlusZero, GmtMinusZero, GmtZero, Greenwich, Hongkong, Hst, Iceland, Iran, Israel, Jamaica,
|
||||||
Japan, Kwajalein, Libya, Met, Mst, Mst7Mdt, Navajo, Nz, NzChat, Poland, Portugal, Prc, Pst8Pdt,
|
Japan, Kwajalein, Libya, Met, Mst, Mst7Mdt, Navajo, Nz, NzChat, Poland, Portugal, Prc, Pst8Pdt,
|
||||||
Roc, Rok, Singapore, Turkey, Uct, Universal, Utc, WSu, Wet, Zulu);
|
Roc, Rok, Singapore, Turkey, Uct, Universal, Utc, WSu, Wet, Zulu);
|
||||||
ENUM(AnisotropyMode, Automatic, Default, X2, X4, X8, X16);
|
ENUM(AnisotropyMode, Automatic, Default, X2, X4, X8, X16, X32, X64, None);
|
||||||
ENUM(AstcDecodeMode, Cpu, Gpu, CpuAsynchronous);
|
ENUM(AstcDecodeMode, Cpu, Gpu, CpuAsynchronous);
|
||||||
ENUM(AstcRecompression, Uncompressed, Bc1, Bc3);
|
ENUM(AstcRecompression, Uncompressed, Bc1, Bc3);
|
||||||
ENUM(FramePacingMode, Target_Auto, Target_30, Target_60, Target_90, Target_120);
|
ENUM(FramePacingMode, Target_Auto, Target_30, Target_60, Target_90, Target_120);
|
||||||
|
|||||||
@@ -286,7 +286,6 @@ void ArmDynarmic32::MakeJit(Common::PageTable* page_table) {
|
|||||||
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA;
|
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA;
|
||||||
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_IgnoreStandardFPCRValue;
|
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_IgnoreStandardFPCRValue;
|
||||||
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_InaccurateNaN;
|
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_InaccurateNaN;
|
||||||
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_IgnoreGlobalMonitor;
|
|
||||||
break;
|
break;
|
||||||
// Paranoia mode for debugging optimizations
|
// Paranoia mode for debugging optimizations
|
||||||
case Settings::CpuAccuracy::Paranoid:
|
case Settings::CpuAccuracy::Paranoid:
|
||||||
|
|||||||
@@ -338,7 +338,6 @@ void ArmDynarmic64::MakeJit(Common::PageTable* page_table, std::size_t address_s
|
|||||||
config.unsafe_optimizations = true;
|
config.unsafe_optimizations = true;
|
||||||
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA;
|
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA;
|
||||||
config.fastmem_address_space_bits = 64;
|
config.fastmem_address_space_bits = 64;
|
||||||
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_IgnoreGlobalMonitor;
|
|
||||||
break;
|
break;
|
||||||
// Paranoia mode for debugging optimizations
|
// Paranoia mode for debugging optimizations
|
||||||
case Settings::CpuAccuracy::Paranoid:
|
case Settings::CpuAccuracy::Paranoid:
|
||||||
|
|||||||
@@ -105,12 +105,7 @@ void LoopProcess(Core::System& system) {
|
|||||||
auto server_manager = std::make_unique<ServerManager>(system);
|
auto server_manager = std::make_unique<ServerManager>(system);
|
||||||
auto module = std::make_shared<Module>(system);
|
auto module = std::make_shared<Module>(system);
|
||||||
server_manager->RegisterNamedService("nvdrv", std::make_shared<NVDRV>(system, module, "nvdrv"));
|
server_manager->RegisterNamedService("nvdrv", std::make_shared<NVDRV>(system, module, "nvdrv"));
|
||||||
|
server_manager->RegisterNamedService("nvdrv:a", std::make_shared<NVDRV>(system, module, "nvdrv:a"));
|
||||||
const auto NvdrvInterfaceFactoryForApplets = [&, module] {
|
|
||||||
return std::make_shared<NVDRV>(system, module, "nvdrv:a");
|
|
||||||
};
|
|
||||||
|
|
||||||
server_manager->RegisterNamedService("nvdrv:a", NvdrvInterfaceFactoryForApplets);
|
|
||||||
server_manager->RegisterNamedService("nvdrv:s", std::make_shared<NVDRV>(system, module, "nvdrv:s"));
|
server_manager->RegisterNamedService("nvdrv:s", std::make_shared<NVDRV>(system, module, "nvdrv:s"));
|
||||||
server_manager->RegisterNamedService("nvdrv:t", std::make_shared<NVDRV>(system, module, "nvdrv:t"));
|
server_manager->RegisterNamedService("nvdrv:t", std::make_shared<NVDRV>(system, module, "nvdrv:t"));
|
||||||
server_manager->RegisterNamedService("nvmemp", std::make_shared<NVMEMP>(system));
|
server_manager->RegisterNamedService("nvmemp", std::make_shared<NVMEMP>(system));
|
||||||
|
|||||||
@@ -588,12 +588,7 @@ void LoopProcess(Core::System& system) {
|
|||||||
auto server_manager = std::make_unique<ServerManager>(system);
|
auto server_manager = std::make_unique<ServerManager>(system);
|
||||||
|
|
||||||
auto ro = std::make_shared<RoContext>();
|
auto ro = std::make_shared<RoContext>();
|
||||||
|
server_manager->RegisterNamedService("ldr:ro", std::make_shared<RoInterface>(system, "ldr:ro", ro, NrrKind::User));
|
||||||
const auto RoInterfaceFactoryForUser = [&, ro] {
|
|
||||||
return std::make_shared<RoInterface>(system, "ldr:ro", ro, NrrKind::User);
|
|
||||||
};
|
|
||||||
|
|
||||||
server_manager->RegisterNamedService("ldr:ro", std::move(RoInterfaceFactoryForUser));
|
|
||||||
server_manager->RegisterNamedService("ro:1", std::make_shared<RoInterface>(system, "ro:1", ro, NrrKind::JitPlugin));
|
server_manager->RegisterNamedService("ro:1", std::make_shared<RoInterface>(system, "ro:1", ro, NrrKind::JitPlugin));
|
||||||
server_manager->RegisterNamedService("ro:dmnt", std::make_shared<IDebugMonitorInterface>(system));
|
server_manager->RegisterNamedService("ro:dmnt", std::make_shared<IDebugMonitorInterface>(system));
|
||||||
ServerManager::RunServer(std::move(server_manager));
|
ServerManager::RunServer(std::move(server_manager));
|
||||||
|
|||||||
@@ -522,6 +522,9 @@ std::unique_ptr<ComboboxTranslationMap> ComboboxEnumeration(QObject* parent) {
|
|||||||
PAIR(AnisotropyMode, X4, tr("4x")),
|
PAIR(AnisotropyMode, X4, tr("4x")),
|
||||||
PAIR(AnisotropyMode, X8, tr("8x")),
|
PAIR(AnisotropyMode, X8, tr("8x")),
|
||||||
PAIR(AnisotropyMode, X16, tr("16x")),
|
PAIR(AnisotropyMode, X16, tr("16x")),
|
||||||
|
PAIR(AnisotropyMode, X32, tr("32x")),
|
||||||
|
PAIR(AnisotropyMode, X64, tr("64x")),
|
||||||
|
PAIR(AnisotropyMode, None, tr("None")),
|
||||||
}});
|
}});
|
||||||
translations->insert(
|
translations->insert(
|
||||||
{Settings::EnumMetadata<Settings::Language>::Index(),
|
{Settings::EnumMetadata<Settings::Language>::Index(),
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ set(SHADER_FILES
|
|||||||
${CMAKE_CURRENT_SOURCE_DIR}/blit_color_float.frag
|
${CMAKE_CURRENT_SOURCE_DIR}/blit_color_float.frag
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/block_linear_unswizzle_2d.comp
|
${CMAKE_CURRENT_SOURCE_DIR}/block_linear_unswizzle_2d.comp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/blit_color_msaa.frag
|
${CMAKE_CURRENT_SOURCE_DIR}/blit_color_msaa.frag
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/blit_depth.frag
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/blit_depth_msaa.frag
|
${CMAKE_CURRENT_SOURCE_DIR}/blit_depth_msaa.frag
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/blit_depth_stencil_msaa.frag
|
${CMAKE_CURRENT_SOURCE_DIR}/blit_depth_stencil_msaa.frag
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/block_linear_unswizzle_3d.comp
|
${CMAKE_CURRENT_SOURCE_DIR}/block_linear_unswizzle_3d.comp
|
||||||
@@ -31,12 +30,8 @@ set(SHADER_FILES
|
|||||||
${CMAKE_CURRENT_SOURCE_DIR}/convert_float_to_depth.frag
|
${CMAKE_CURRENT_SOURCE_DIR}/convert_float_to_depth.frag
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/convert_msaa_to_non_msaa.comp
|
${CMAKE_CURRENT_SOURCE_DIR}/convert_msaa_to_non_msaa.comp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/convert_msaa_to_non_msaa.frag
|
${CMAKE_CURRENT_SOURCE_DIR}/convert_msaa_to_non_msaa.frag
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/convert_msaa_to_non_msaa_depth.frag
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/convert_msaa_to_non_msaa_depth_stencil.frag
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/convert_non_msaa_to_msaa.comp
|
${CMAKE_CURRENT_SOURCE_DIR}/convert_non_msaa_to_msaa.comp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/convert_non_msaa_to_msaa.frag
|
${CMAKE_CURRENT_SOURCE_DIR}/convert_non_msaa_to_msaa.frag
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/convert_non_msaa_to_msaa_depth.frag
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/convert_non_msaa_to_msaa_depth_stencil.frag
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/convert_s8d24_to_abgr8.frag
|
${CMAKE_CURRENT_SOURCE_DIR}/convert_s8d24_to_abgr8.frag
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/full_screen_triangle.vert
|
${CMAKE_CURRENT_SOURCE_DIR}/full_screen_triangle.vert
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/fxaa.frag
|
${CMAKE_CURRENT_SOURCE_DIR}/fxaa.frag
|
||||||
@@ -168,44 +163,6 @@ foreach(SOURCE_FILE IN ITEMS ${SHADER_FILES})
|
|||||||
endif()
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
# Integer variants of the MSAA conversion shaders. They only differ from the float
|
|
||||||
# source in the sampler and output types, so they are generated from it via defines.
|
|
||||||
set(SHADER_TYPE_VARIANTS
|
|
||||||
"convert_msaa_to_non_msaa.frag|sint|isampler2DMS|ivec4"
|
|
||||||
"convert_msaa_to_non_msaa.frag|uint|usampler2DMS|uvec4"
|
|
||||||
"convert_non_msaa_to_msaa.frag|sint|isampler2D|ivec4"
|
|
||||||
"convert_non_msaa_to_msaa.frag|uint|usampler2D|uvec4"
|
|
||||||
)
|
|
||||||
|
|
||||||
foreach(VARIANT IN ITEMS ${SHADER_TYPE_VARIANTS})
|
|
||||||
string(REPLACE "|" ";" VARIANT_PARTS ${VARIANT})
|
|
||||||
list(GET VARIANT_PARTS 0 VARIANT_FILENAME)
|
|
||||||
list(GET VARIANT_PARTS 1 VARIANT_SUFFIX)
|
|
||||||
list(GET VARIANT_PARTS 2 VARIANT_SAMPLER)
|
|
||||||
list(GET VARIANT_PARTS 3 VARIANT_TEXEL)
|
|
||||||
|
|
||||||
set(VARIANT_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/${VARIANT_FILENAME})
|
|
||||||
get_filename_component(VARIANT_STEM ${VARIANT_FILENAME} NAME_WE)
|
|
||||||
get_filename_component(VARIANT_EXT ${VARIANT_FILENAME} EXT)
|
|
||||||
string(REPLACE "." "" VARIANT_EXT ${VARIANT_EXT})
|
|
||||||
set(VARIANT_NAME ${VARIANT_STEM}_${VARIANT_SUFFIX}_${VARIANT_EXT})
|
|
||||||
|
|
||||||
string(TOUPPER ${VARIANT_NAME}_SPV VARIANT_VARIABLE_NAME)
|
|
||||||
set(VARIANT_HEADER_FILE ${SHADER_DIR}/${VARIANT_NAME}_spv.h)
|
|
||||||
add_custom_command(
|
|
||||||
OUTPUT
|
|
||||||
${VARIANT_HEADER_FILE}
|
|
||||||
COMMAND
|
|
||||||
${GLSLANGVALIDATOR} -V ${QUIET_FLAG} -I"${FIDELITYFX_INCLUDE_DIR}" ${GLSL_FLAGS}
|
|
||||||
-DSAMPLER_TYPE=${VARIANT_SAMPLER} -DTEXEL_TYPE=${VARIANT_TEXEL}
|
|
||||||
--variable-name ${VARIANT_VARIABLE_NAME} -o ${VARIANT_HEADER_FILE} ${VARIANT_SOURCE}
|
|
||||||
--target-env ${SPIR_V_VERSION}
|
|
||||||
MAIN_DEPENDENCY
|
|
||||||
${VARIANT_SOURCE}
|
|
||||||
)
|
|
||||||
set(SHADER_HEADERS ${SHADER_HEADERS} ${VARIANT_HEADER_FILE})
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
foreach(FILEPATH IN ITEMS ${FIDELITYFX_FILES})
|
foreach(FILEPATH IN ITEMS ${FIDELITYFX_FILES})
|
||||||
get_filename_component(FILENAME ${FILEPATH} NAME)
|
get_filename_component(FILENAME ${FILEPATH} NAME)
|
||||||
string(REPLACE "." "_" HEADER_NAME ${FILENAME})
|
string(REPLACE "." "_" HEADER_NAME ${FILENAME})
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
#version 450 core
|
|
||||||
|
|
||||||
layout(binding = 0) uniform sampler2D depth_tex;
|
|
||||||
|
|
||||||
layout(location = 0) in vec2 texcoord;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
gl_FragDepth = textureLod(depth_tex, texcoord, 0).r;
|
|
||||||
}
|
|
||||||
@@ -8,5 +8,5 @@ layout(binding = 0) uniform sampler2DMS depth_tex;
|
|||||||
layout(location = 0) in vec2 texcoord;
|
layout(location = 0) in vec2 texcoord;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
gl_FragDepth = texelFetch(depth_tex, ivec2(texcoord), gl_SampleID).r;
|
gl_FragDepth = texelFetch(depth_tex, ivec2(texcoord), 0).r;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,6 @@ layout(binding = 1) uniform usampler2DMS stencil_tex;
|
|||||||
layout(location = 0) in vec2 texcoord;
|
layout(location = 0) in vec2 texcoord;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
gl_FragDepth = texelFetch(depth_tex, ivec2(texcoord), gl_SampleID).r;
|
gl_FragDepth = texelFetch(depth_tex, ivec2(texcoord), 0).r;
|
||||||
gl_FragStencilRefARB = int(texelFetch(stencil_tex, ivec2(texcoord), gl_SampleID).r);
|
gl_FragStencilRefARB = int(texelFetch(stencil_tex, ivec2(texcoord), 0).r);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,14 +3,7 @@
|
|||||||
|
|
||||||
#version 450 core
|
#version 450 core
|
||||||
|
|
||||||
#ifndef SAMPLER_TYPE
|
layout(binding = 0) uniform sampler2DMS msaa_in;
|
||||||
#define SAMPLER_TYPE sampler2DMS
|
|
||||||
#endif
|
|
||||||
#ifndef TEXEL_TYPE
|
|
||||||
#define TEXEL_TYPE vec4
|
|
||||||
#endif
|
|
||||||
|
|
||||||
layout(binding = 0) uniform SAMPLER_TYPE msaa_in;
|
|
||||||
|
|
||||||
layout(push_constant) uniform PushConstants {
|
layout(push_constant) uniform PushConstants {
|
||||||
ivec2 dst_offset;
|
ivec2 dst_offset;
|
||||||
@@ -18,7 +11,7 @@ layout(push_constant) uniform PushConstants {
|
|||||||
ivec2 scale;
|
ivec2 scale;
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(location = 0) out TEXEL_TYPE frag_color;
|
layout(location = 0) out vec4 frag_color;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
const ivec2 coord = ivec2(gl_FragCoord.xy) - dst_offset + src_offset;
|
const ivec2 coord = ivec2(gl_FragCoord.xy) - dst_offset + src_offset;
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
#version 450 core
|
|
||||||
|
|
||||||
layout(binding = 0) uniform sampler2DMS msaa_in;
|
|
||||||
|
|
||||||
layout(push_constant) uniform PushConstants {
|
|
||||||
ivec2 dst_offset;
|
|
||||||
ivec2 src_offset;
|
|
||||||
ivec2 scale;
|
|
||||||
};
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
const ivec2 coord = ivec2(gl_FragCoord.xy) - dst_offset + src_offset;
|
|
||||||
const ivec2 msaa_coord = coord / scale;
|
|
||||||
const ivec2 sample_offset = coord % scale;
|
|
||||||
const int sample_id = sample_offset.x + scale.x * sample_offset.y;
|
|
||||||
gl_FragDepth = texelFetch(msaa_in, msaa_coord, sample_id).r;
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
#version 450 core
|
|
||||||
#extension GL_ARB_shader_stencil_export : require
|
|
||||||
|
|
||||||
layout(binding = 0) uniform sampler2DMS depth_tex;
|
|
||||||
layout(binding = 1) uniform usampler2DMS stencil_tex;
|
|
||||||
|
|
||||||
layout(push_constant) uniform PushConstants {
|
|
||||||
ivec2 dst_offset;
|
|
||||||
ivec2 src_offset;
|
|
||||||
ivec2 scale;
|
|
||||||
};
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
const ivec2 coord = ivec2(gl_FragCoord.xy) - dst_offset + src_offset;
|
|
||||||
const ivec2 msaa_coord = coord / scale;
|
|
||||||
const ivec2 sample_offset = coord % scale;
|
|
||||||
const int sample_id = sample_offset.x + scale.x * sample_offset.y;
|
|
||||||
gl_FragDepth = texelFetch(depth_tex, msaa_coord, sample_id).r;
|
|
||||||
gl_FragStencilRefARB = int(texelFetch(stencil_tex, msaa_coord, sample_id).r);
|
|
||||||
}
|
|
||||||
@@ -3,14 +3,7 @@
|
|||||||
|
|
||||||
#version 450 core
|
#version 450 core
|
||||||
|
|
||||||
#ifndef SAMPLER_TYPE
|
layout(binding = 0) uniform sampler2D img_in;
|
||||||
#define SAMPLER_TYPE sampler2D
|
|
||||||
#endif
|
|
||||||
#ifndef TEXEL_TYPE
|
|
||||||
#define TEXEL_TYPE vec4
|
|
||||||
#endif
|
|
||||||
|
|
||||||
layout(binding = 0) uniform SAMPLER_TYPE img_in;
|
|
||||||
|
|
||||||
layout(push_constant) uniform PushConstants {
|
layout(push_constant) uniform PushConstants {
|
||||||
ivec2 dst_offset;
|
ivec2 dst_offset;
|
||||||
@@ -18,7 +11,7 @@ layout(push_constant) uniform PushConstants {
|
|||||||
ivec2 scale;
|
ivec2 scale;
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(location = 0) out TEXEL_TYPE frag_color;
|
layout(location = 0) out vec4 frag_color;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
const ivec2 msaa_coord = ivec2(gl_FragCoord.xy) - dst_offset;
|
const ivec2 msaa_coord = ivec2(gl_FragCoord.xy) - dst_offset;
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
#version 450 core
|
|
||||||
|
|
||||||
layout(binding = 0) uniform sampler2D img_in;
|
|
||||||
|
|
||||||
layout(push_constant) uniform PushConstants {
|
|
||||||
ivec2 dst_offset;
|
|
||||||
ivec2 src_offset;
|
|
||||||
ivec2 scale;
|
|
||||||
};
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
const ivec2 msaa_coord = ivec2(gl_FragCoord.xy) - dst_offset;
|
|
||||||
const ivec2 sample_offset = ivec2(gl_SampleID % scale.x, gl_SampleID / scale.x);
|
|
||||||
const ivec2 coord = msaa_coord * scale + sample_offset + src_offset;
|
|
||||||
gl_FragDepth = texelFetch(img_in, coord, 0).r;
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
#version 450 core
|
|
||||||
#extension GL_ARB_shader_stencil_export : require
|
|
||||||
|
|
||||||
layout(binding = 0) uniform sampler2D depth_tex;
|
|
||||||
layout(binding = 1) uniform usampler2D stencil_tex;
|
|
||||||
|
|
||||||
layout(push_constant) uniform PushConstants {
|
|
||||||
ivec2 dst_offset;
|
|
||||||
ivec2 src_offset;
|
|
||||||
ivec2 scale;
|
|
||||||
};
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
const ivec2 msaa_coord = ivec2(gl_FragCoord.xy) - dst_offset;
|
|
||||||
const ivec2 sample_offset = ivec2(gl_SampleID % scale.x, gl_SampleID / scale.x);
|
|
||||||
const ivec2 coord = msaa_coord * scale + sample_offset + src_offset;
|
|
||||||
gl_FragDepth = texelFetch(depth_tex, coord, 0).r;
|
|
||||||
gl_FragStencilRefARB = int(texelFetch(stencil_tex, coord, 0).r);
|
|
||||||
}
|
|
||||||
@@ -7,7 +7,6 @@ layout(push_constant) uniform constants {
|
|||||||
vec2 scale;
|
vec2 scale;
|
||||||
vec2 size;
|
vec2 size;
|
||||||
vec2 resize_factor;
|
vec2 resize_factor;
|
||||||
vec2 crop_offset;
|
|
||||||
float edge_sharpness;
|
float edge_sharpness;
|
||||||
};
|
};
|
||||||
layout(location = 0) out highp vec2 texcoord;
|
layout(location = 0) out highp vec2 texcoord;
|
||||||
@@ -16,5 +15,5 @@ void main() {
|
|||||||
float x = float((gl_VertexIndex & 1) << 2);
|
float x = float((gl_VertexIndex & 1) << 2);
|
||||||
float y = float((gl_VertexIndex & 2) << 1);
|
float y = float((gl_VertexIndex & 2) << 1);
|
||||||
gl_Position = vec4(x - 1.0f, y - 1.0f, 0.0, 1.0f) * vec4(sign(resize_factor), 1.f, 1.f);
|
gl_Position = vec4(x - 1.0f, y - 1.0f, 0.0, 1.0f) * vec4(sign(resize_factor), 1.f, 1.f);
|
||||||
texcoord = crop_offset + vec2(x, y) * abs(resize_factor) * 0.5;
|
texcoord = vec2(x, y) * abs(resize_factor) * 0.5;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ layout(push_constant) uniform constants {
|
|||||||
vec2 scale;
|
vec2 scale;
|
||||||
vec2 size;
|
vec2 size;
|
||||||
vec2 resize_factor;
|
vec2 resize_factor;
|
||||||
vec2 crop_offset;
|
|
||||||
float edge_sharpness;
|
float edge_sharpness;
|
||||||
};
|
};
|
||||||
layout(set = 0, binding = 0) uniform sampler2D sampler0;
|
layout(set = 0, binding = 0) uniform sampler2D sampler0;
|
||||||
|
|||||||
@@ -13,7 +13,6 @@
|
|||||||
layout( push_constant ) uniform constants {
|
layout( push_constant ) uniform constants {
|
||||||
vec4 ViewportInfo[1];
|
vec4 ViewportInfo[1];
|
||||||
vec2 ResizeFactor;
|
vec2 ResizeFactor;
|
||||||
vec2 CropOffset;
|
|
||||||
float EdgeSharpness;
|
float EdgeSharpness;
|
||||||
};
|
};
|
||||||
layout(set = 0, binding = 0) uniform sampler2D ps0;
|
layout(set = 0, binding = 0) uniform sampler2D ps0;
|
||||||
|
|||||||
@@ -75,8 +75,6 @@ public:
|
|||||||
|
|
||||||
void Finish();
|
void Finish();
|
||||||
|
|
||||||
void FlushDeferredClear() {}
|
|
||||||
|
|
||||||
StagingBufferMap UploadStagingBuffer(size_t size, bool deferred = false);
|
StagingBufferMap UploadStagingBuffer(size_t size, bool deferred = false);
|
||||||
|
|
||||||
StagingBufferMap DownloadStagingBuffer(size_t size, bool deferred = false);
|
StagingBufferMap DownloadStagingBuffer(size_t size, bool deferred = false);
|
||||||
@@ -372,7 +370,6 @@ struct TextureCacheParams {
|
|||||||
static constexpr bool HAS_EMULATED_COPIES = true;
|
static constexpr bool HAS_EMULATED_COPIES = true;
|
||||||
static constexpr bool HAS_DEVICE_MEMORY_INFO = true;
|
static constexpr bool HAS_DEVICE_MEMORY_INFO = true;
|
||||||
static constexpr bool IMPLEMENTS_ASYNC_DOWNLOADS = true;
|
static constexpr bool IMPLEMENTS_ASYNC_DOWNLOADS = true;
|
||||||
static constexpr bool HAS_MSAA_DOWNLOADS = false;
|
|
||||||
|
|
||||||
using Runtime = OpenGL::TextureCacheRuntime;
|
using Runtime = OpenGL::TextureCacheRuntime;
|
||||||
using Image = OpenGL::Image;
|
using Image = OpenGL::Image;
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
#include "video_core/host_shaders/blit_color_float_frag_spv.h"
|
#include "video_core/host_shaders/blit_color_float_frag_spv.h"
|
||||||
#include "video_core/host_shaders/blit_color_msaa_frag_spv.h"
|
#include "video_core/host_shaders/blit_color_msaa_frag_spv.h"
|
||||||
#include "video_core/host_shaders/blit_depth_frag_spv.h"
|
|
||||||
#include "video_core/host_shaders/blit_depth_msaa_frag_spv.h"
|
#include "video_core/host_shaders/blit_depth_msaa_frag_spv.h"
|
||||||
#include "video_core/host_shaders/blit_depth_stencil_msaa_frag_spv.h"
|
#include "video_core/host_shaders/blit_depth_stencil_msaa_frag_spv.h"
|
||||||
#include "video_core/host_shaders/convert_abgr8_to_d24s8_frag_spv.h"
|
#include "video_core/host_shaders/convert_abgr8_to_d24s8_frag_spv.h"
|
||||||
@@ -22,15 +21,7 @@
|
|||||||
#include "video_core/host_shaders/convert_depth_to_float_frag_spv.h"
|
#include "video_core/host_shaders/convert_depth_to_float_frag_spv.h"
|
||||||
#include "video_core/host_shaders/convert_float_to_depth_frag_spv.h"
|
#include "video_core/host_shaders/convert_float_to_depth_frag_spv.h"
|
||||||
#include "video_core/host_shaders/convert_msaa_to_non_msaa_frag_spv.h"
|
#include "video_core/host_shaders/convert_msaa_to_non_msaa_frag_spv.h"
|
||||||
#include "video_core/host_shaders/convert_msaa_to_non_msaa_depth_frag_spv.h"
|
|
||||||
#include "video_core/host_shaders/convert_msaa_to_non_msaa_depth_stencil_frag_spv.h"
|
|
||||||
#include "video_core/host_shaders/convert_msaa_to_non_msaa_sint_frag_spv.h"
|
|
||||||
#include "video_core/host_shaders/convert_msaa_to_non_msaa_uint_frag_spv.h"
|
|
||||||
#include "video_core/host_shaders/convert_non_msaa_to_msaa_frag_spv.h"
|
#include "video_core/host_shaders/convert_non_msaa_to_msaa_frag_spv.h"
|
||||||
#include "video_core/host_shaders/convert_non_msaa_to_msaa_sint_frag_spv.h"
|
|
||||||
#include "video_core/host_shaders/convert_non_msaa_to_msaa_uint_frag_spv.h"
|
|
||||||
#include "video_core/host_shaders/convert_non_msaa_to_msaa_depth_frag_spv.h"
|
|
||||||
#include "video_core/host_shaders/convert_non_msaa_to_msaa_depth_stencil_frag_spv.h"
|
|
||||||
#include "video_core/host_shaders/convert_s8d24_to_abgr8_frag_spv.h"
|
#include "video_core/host_shaders/convert_s8d24_to_abgr8_frag_spv.h"
|
||||||
#include "video_core/host_shaders/full_screen_triangle_vert_spv.h"
|
#include "video_core/host_shaders/full_screen_triangle_vert_spv.h"
|
||||||
#include "video_core/host_shaders/vulkan_blit_depth_stencil_frag_spv.h"
|
#include "video_core/host_shaders/vulkan_blit_depth_stencil_frag_spv.h"
|
||||||
@@ -527,19 +518,8 @@ void RecordShaderReadBarrier(Scheduler& scheduler, const ImageView& image_view)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] MSAACopyFormatClass FormatClass(VideoCore::Surface::PixelFormat format) {
|
|
||||||
if (!VideoCore::Surface::IsPixelFormatInteger(format)) {
|
|
||||||
return MSAACopyFormatClass::Float;
|
|
||||||
}
|
|
||||||
if (VideoCore::Surface::IsPixelFormatSignedInteger(format)) {
|
|
||||||
return MSAACopyFormatClass::SignedInteger;
|
|
||||||
}
|
|
||||||
return MSAACopyFormatClass::UnsignedInteger;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] vk::ImageView MakeMSAACopyView(const vk::Device& device, VkImage image,
|
[[nodiscard]] vk::ImageView MakeMSAACopyView(const vk::Device& device, VkImage image,
|
||||||
VkFormat format, u32 base_level, u32 base_layer,
|
VkFormat format, u32 base_level) {
|
||||||
VkImageAspectFlags aspect_mask) {
|
|
||||||
return device.CreateImageView(VkImageViewCreateInfo{
|
return device.CreateImageView(VkImageViewCreateInfo{
|
||||||
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
@@ -554,10 +534,10 @@ void RecordShaderReadBarrier(Scheduler& scheduler, const ImageView& image_view)
|
|||||||
.a = VK_COMPONENT_SWIZZLE_IDENTITY,
|
.a = VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||||
},
|
},
|
||||||
.subresourceRange{
|
.subresourceRange{
|
||||||
.aspectMask = aspect_mask,
|
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
.baseMipLevel = base_level,
|
.baseMipLevel = base_level,
|
||||||
.levelCount = 1,
|
.levelCount = 1,
|
||||||
.baseArrayLayer = base_layer,
|
.baseArrayLayer = 0,
|
||||||
.layerCount = 1,
|
.layerCount = 1,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -606,17 +586,12 @@ BlitImageHelper::BlitImageHelper(const Device& device_, Scheduler& scheduler_,
|
|||||||
msaa_copy_pipeline_layout(device.GetLogical().CreatePipelineLayout(PipelineLayoutCreateInfo(
|
msaa_copy_pipeline_layout(device.GetLogical().CreatePipelineLayout(PipelineLayoutCreateInfo(
|
||||||
one_texture_set_layout.address(),
|
one_texture_set_layout.address(),
|
||||||
PUSH_CONSTANT_RANGE<VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(MSAACopyPushConstants)>))),
|
PUSH_CONSTANT_RANGE<VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(MSAACopyPushConstants)>))),
|
||||||
msaa_copy_depth_stencil_pipeline_layout(
|
|
||||||
device.GetLogical().CreatePipelineLayout(PipelineLayoutCreateInfo(
|
|
||||||
two_textures_set_layout.address(),
|
|
||||||
PUSH_CONSTANT_RANGE<VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(MSAACopyPushConstants)>))),
|
|
||||||
full_screen_vert(BuildShader(device, FULL_SCREEN_TRIANGLE_VERT_SPV)),
|
full_screen_vert(BuildShader(device, FULL_SCREEN_TRIANGLE_VERT_SPV)),
|
||||||
blit_color_to_color_frag(BuildShader(device, BLIT_COLOR_FLOAT_FRAG_SPV)),
|
blit_color_to_color_frag(BuildShader(device, BLIT_COLOR_FLOAT_FRAG_SPV)),
|
||||||
blit_color_msaa_frag(BuildShader(device, BLIT_COLOR_MSAA_FRAG_SPV)),
|
blit_color_msaa_frag(BuildShader(device, BLIT_COLOR_MSAA_FRAG_SPV)),
|
||||||
blit_depth_stencil_frag(device.IsExtShaderStencilExportSupported()
|
blit_depth_stencil_frag(device.IsExtShaderStencilExportSupported()
|
||||||
? BuildShader(device, VULKAN_BLIT_DEPTH_STENCIL_FRAG_SPV)
|
? BuildShader(device, VULKAN_BLIT_DEPTH_STENCIL_FRAG_SPV)
|
||||||
: vk::ShaderModule{}),
|
: vk::ShaderModule{}),
|
||||||
blit_depth_frag(BuildShader(device, BLIT_DEPTH_FRAG_SPV)),
|
|
||||||
blit_depth_msaa_frag(BuildShader(device, BLIT_DEPTH_MSAA_FRAG_SPV)),
|
blit_depth_msaa_frag(BuildShader(device, BLIT_DEPTH_MSAA_FRAG_SPV)),
|
||||||
blit_depth_stencil_msaa_frag(device.IsExtShaderStencilExportSupported()
|
blit_depth_stencil_msaa_frag(device.IsExtShaderStencilExportSupported()
|
||||||
? BuildShader(device, BLIT_DEPTH_STENCIL_MSAA_FRAG_SPV)
|
? BuildShader(device, BLIT_DEPTH_STENCIL_MSAA_FRAG_SPV)
|
||||||
@@ -634,25 +609,7 @@ BlitImageHelper::BlitImageHelper(const Device& device_, Scheduler& scheduler_,
|
|||||||
convert_d24s8_to_abgr8_frag(BuildShader(device, CONVERT_D24S8_TO_ABGR8_FRAG_SPV)),
|
convert_d24s8_to_abgr8_frag(BuildShader(device, CONVERT_D24S8_TO_ABGR8_FRAG_SPV)),
|
||||||
convert_s8d24_to_abgr8_frag(BuildShader(device, CONVERT_S8D24_TO_ABGR8_FRAG_SPV)),
|
convert_s8d24_to_abgr8_frag(BuildShader(device, CONVERT_S8D24_TO_ABGR8_FRAG_SPV)),
|
||||||
convert_msaa_to_non_msaa_frag(BuildShader(device, CONVERT_MSAA_TO_NON_MSAA_FRAG_SPV)),
|
convert_msaa_to_non_msaa_frag(BuildShader(device, CONVERT_MSAA_TO_NON_MSAA_FRAG_SPV)),
|
||||||
convert_msaa_to_non_msaa_sint_frag(
|
|
||||||
BuildShader(device, CONVERT_MSAA_TO_NON_MSAA_SINT_FRAG_SPV)),
|
|
||||||
convert_msaa_to_non_msaa_uint_frag(
|
|
||||||
BuildShader(device, CONVERT_MSAA_TO_NON_MSAA_UINT_FRAG_SPV)),
|
|
||||||
convert_msaa_to_non_msaa_depth_frag(
|
|
||||||
BuildShader(device, CONVERT_MSAA_TO_NON_MSAA_DEPTH_FRAG_SPV)),
|
|
||||||
convert_msaa_to_non_msaa_depth_stencil_frag(
|
|
||||||
BuildShader(device, CONVERT_MSAA_TO_NON_MSAA_DEPTH_STENCIL_FRAG_SPV)),
|
|
||||||
convert_non_msaa_to_msaa_frag(BuildShader(device, CONVERT_NON_MSAA_TO_MSAA_FRAG_SPV)),
|
convert_non_msaa_to_msaa_frag(BuildShader(device, CONVERT_NON_MSAA_TO_MSAA_FRAG_SPV)),
|
||||||
convert_non_msaa_to_msaa_sint_frag(
|
|
||||||
BuildShader(device, CONVERT_NON_MSAA_TO_MSAA_SINT_FRAG_SPV)),
|
|
||||||
convert_non_msaa_to_msaa_uint_frag(
|
|
||||||
BuildShader(device, CONVERT_NON_MSAA_TO_MSAA_UINT_FRAG_SPV)),
|
|
||||||
convert_non_msaa_to_msaa_depth_frag(
|
|
||||||
BuildShader(device, CONVERT_NON_MSAA_TO_MSAA_DEPTH_FRAG_SPV)),
|
|
||||||
convert_non_msaa_to_msaa_depth_stencil_frag(
|
|
||||||
device.IsExtShaderStencilExportSupported()
|
|
||||||
? BuildShader(device, CONVERT_NON_MSAA_TO_MSAA_DEPTH_STENCIL_FRAG_SPV)
|
|
||||||
: vk::ShaderModule{}),
|
|
||||||
linear_sampler(device.GetLogical().CreateSampler(SAMPLER_CREATE_INFO<VK_FILTER_LINEAR>)),
|
linear_sampler(device.GetLogical().CreateSampler(SAMPLER_CREATE_INFO<VK_FILTER_LINEAR>)),
|
||||||
nearest_sampler(device.GetLogical().CreateSampler(SAMPLER_CREATE_INFO<VK_FILTER_NEAREST>)) {}
|
nearest_sampler(device.GetLogical().CreateSampler(SAMPLER_CREATE_INFO<VK_FILTER_NEAREST>)) {}
|
||||||
|
|
||||||
@@ -667,13 +624,24 @@ void BlitImageHelper::BlitColor(const Framebuffer* dst_framebuffer, const ImageV
|
|||||||
.renderpass = dst_framebuffer->RenderPass(),
|
.renderpass = dst_framebuffer->RenderPass(),
|
||||||
.operation = operation,
|
.operation = operation,
|
||||||
};
|
};
|
||||||
VkSampler sampler = *nearest_sampler;
|
const VkPipelineLayout layout = *one_texture_pipeline_layout;
|
||||||
if (is_linear) {
|
const VkSampler sampler = is_linear ? *linear_sampler : *nearest_sampler;
|
||||||
sampler = *linear_sampler;
|
const VkPipeline pipeline = FindOrEmplaceColorPipeline(key);
|
||||||
}
|
const VkImageView src_view = src_image_view.Handle(Shader::TextureType::Color2D);
|
||||||
BlitImpl(dst_framebuffer, src_image_view, dst_region, src_region,
|
|
||||||
FindOrEmplaceColorPipeline(key), sampler,
|
RecordShaderReadBarrier(scheduler, src_image_view);
|
||||||
src_image_view.Handle(Shader::TextureType::Color2D), VK_NULL_HANDLE, false);
|
scheduler.RequestRenderpass(dst_framebuffer);
|
||||||
|
scheduler.Record([this, dst_region, src_region, pipeline, layout, sampler,
|
||||||
|
src_view](vk::CommandBuffer cmdbuf) {
|
||||||
|
const VkDescriptorSet descriptor_set = one_texture_descriptor_allocator.Commit();
|
||||||
|
UpdateOneTextureDescriptorSet(device, descriptor_set, sampler, src_view);
|
||||||
|
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
||||||
|
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptor_set,
|
||||||
|
nullptr);
|
||||||
|
BindBlitState(cmdbuf, layout, dst_region, src_region);
|
||||||
|
cmdbuf.Draw(3, 1, 0, 0);
|
||||||
|
});
|
||||||
|
scheduler.InvalidateState();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlitImageHelper::BlitColor(const Framebuffer* dst_framebuffer, VkImageView src_image_view,
|
void BlitImageHelper::BlitColor(const Framebuffer* dst_framebuffer, VkImageView src_image_view,
|
||||||
@@ -702,29 +670,24 @@ void BlitImageHelper::BlitColor(const Framebuffer* dst_framebuffer, VkImageView
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlitImageHelper::BlitImpl(const Framebuffer* dst_framebuffer,
|
void BlitImageHelper::BlitColorMSAA(const Framebuffer* dst_framebuffer,
|
||||||
const ImageView& src_image_view, const Region2D& dst_region,
|
const ImageView& src_image_view, const Region2D& dst_region,
|
||||||
const Region2D& src_region, VkPipeline pipeline, VkSampler sampler,
|
const Region2D& src_region) {
|
||||||
VkImageView src_view, VkImageView src_stencil_view,
|
const BlitMSAAPipelineKey key{
|
||||||
bool blit_stencil) {
|
.renderpass = dst_framebuffer->RenderPass(),
|
||||||
VkPipelineLayout layout = *one_texture_pipeline_layout;
|
.samples = dst_framebuffer->Samples(),
|
||||||
if (blit_stencil) {
|
};
|
||||||
layout = *two_textures_pipeline_layout;
|
const VkPipelineLayout layout = *one_texture_pipeline_layout;
|
||||||
}
|
const VkSampler sampler = *nearest_sampler;
|
||||||
|
const VkPipeline pipeline = FindOrEmplaceBlitColorMSAAPipeline(key);
|
||||||
|
const VkImageView src_view = src_image_view.Handle(Shader::TextureType::Color2D);
|
||||||
|
|
||||||
RecordShaderReadBarrier(scheduler, src_image_view);
|
RecordShaderReadBarrier(scheduler, src_image_view);
|
||||||
scheduler.RequestRenderpass(dst_framebuffer);
|
scheduler.RequestRenderpass(dst_framebuffer);
|
||||||
scheduler.Record([this, dst_region, src_region, pipeline, layout, sampler, src_view,
|
scheduler.Record([this, dst_region, src_region, pipeline, layout, sampler,
|
||||||
src_stencil_view, blit_stencil](vk::CommandBuffer cmdbuf) {
|
src_view](vk::CommandBuffer cmdbuf) {
|
||||||
VkDescriptorSet descriptor_set = VK_NULL_HANDLE;
|
const VkDescriptorSet descriptor_set = one_texture_descriptor_allocator.Commit();
|
||||||
if (blit_stencil) {
|
UpdateOneTextureDescriptorSet(device, descriptor_set, sampler, src_view);
|
||||||
descriptor_set = two_textures_descriptor_allocator.Commit();
|
|
||||||
UpdateTwoTexturesDescriptorSet(device, descriptor_set, sampler, src_view,
|
|
||||||
src_stencil_view);
|
|
||||||
} else {
|
|
||||||
descriptor_set = one_texture_descriptor_allocator.Commit();
|
|
||||||
UpdateOneTextureDescriptorSet(device, descriptor_set, sampler, src_view);
|
|
||||||
}
|
|
||||||
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
||||||
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptor_set,
|
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptor_set,
|
||||||
nullptr);
|
nullptr);
|
||||||
@@ -734,56 +697,41 @@ void BlitImageHelper::BlitImpl(const Framebuffer* dst_framebuffer,
|
|||||||
scheduler.InvalidateState();
|
scheduler.InvalidateState();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlitImageHelper::BlitColorMSAA(const Framebuffer* dst_framebuffer,
|
|
||||||
const ImageView& src_image_view, const Region2D& dst_region,
|
|
||||||
const Region2D& src_region) {
|
|
||||||
const BlitMSAAPipelineKey key{
|
|
||||||
.renderpass = dst_framebuffer->RenderPass(),
|
|
||||||
.samples = dst_framebuffer->Samples(),
|
|
||||||
};
|
|
||||||
BlitImpl(dst_framebuffer, src_image_view, dst_region, src_region,
|
|
||||||
FindOrEmplaceBlitColorMSAAPipeline(key), *nearest_sampler,
|
|
||||||
src_image_view.Handle(Shader::TextureType::Color2D), VK_NULL_HANDLE, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BlitImageHelper::BlitDepthStencilMSAA(const Framebuffer* dst_framebuffer,
|
|
||||||
ImageView& src_image_view, const Region2D& dst_region,
|
|
||||||
const Region2D& src_region) {
|
|
||||||
const bool blit_stencil =
|
|
||||||
dst_framebuffer->HasAspectStencilBit() && device.IsExtShaderStencilExportSupported();
|
|
||||||
const BlitMSAAPipelineKey key{
|
|
||||||
.renderpass = dst_framebuffer->RenderPass(),
|
|
||||||
.samples = dst_framebuffer->Samples(),
|
|
||||||
};
|
|
||||||
VkImageView src_stencil_view = VK_NULL_HANDLE;
|
|
||||||
if (blit_stencil) {
|
|
||||||
src_stencil_view = src_image_view.StencilView();
|
|
||||||
}
|
|
||||||
BlitImpl(dst_framebuffer, src_image_view, dst_region, src_region,
|
|
||||||
FindOrEmplaceBlitDepthStencilMSAAPipeline(key, blit_stencil), *nearest_sampler,
|
|
||||||
src_image_view.DepthView(), src_stencil_view, blit_stencil);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BlitImageHelper::BlitDepth(const Framebuffer* dst_framebuffer, ImageView& src_image_view,
|
|
||||||
const Region2D& dst_region, const Region2D& src_region) {
|
|
||||||
BlitImpl(dst_framebuffer, src_image_view, dst_region, src_region,
|
|
||||||
FindOrEmplaceBlitDepthPipeline(dst_framebuffer->RenderPass()), *nearest_sampler,
|
|
||||||
src_image_view.DepthView(), VK_NULL_HANDLE, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BlitImageHelper::ResolveDepthStencil(const Framebuffer* dst_framebuffer,
|
void BlitImageHelper::ResolveDepthStencil(const Framebuffer* dst_framebuffer,
|
||||||
ImageView& src_image_view, const Region2D& dst_region,
|
ImageView& src_image_view, const Region2D& dst_region,
|
||||||
const Region2D& src_region) {
|
const Region2D& src_region) {
|
||||||
const bool resolve_stencil =
|
const bool resolve_stencil =
|
||||||
dst_framebuffer->HasAspectStencilBit() && device.IsExtShaderStencilExportSupported();
|
dst_framebuffer->HasAspectStencilBit() && device.IsExtShaderStencilExportSupported();
|
||||||
VkImageView src_stencil_view = VK_NULL_HANDLE;
|
const VkPipeline pipeline =
|
||||||
if (resolve_stencil) {
|
FindOrEmplaceResolveDepthStencilPipeline(dst_framebuffer->RenderPass(), resolve_stencil);
|
||||||
src_stencil_view = src_image_view.StencilView();
|
const VkPipelineLayout layout =
|
||||||
}
|
resolve_stencil ? *two_textures_pipeline_layout : *one_texture_pipeline_layout;
|
||||||
BlitImpl(dst_framebuffer, src_image_view, dst_region, src_region,
|
const VkSampler sampler = *nearest_sampler;
|
||||||
FindOrEmplaceResolveDepthStencilPipeline(dst_framebuffer->RenderPass(),
|
const VkImageView src_depth_view = src_image_view.DepthView();
|
||||||
resolve_stencil),
|
const VkImageView src_stencil_view =
|
||||||
*nearest_sampler, src_image_view.DepthView(), src_stencil_view, resolve_stencil);
|
resolve_stencil ? src_image_view.StencilView() : VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
RecordShaderReadBarrier(scheduler, src_image_view);
|
||||||
|
scheduler.RequestRenderpass(dst_framebuffer);
|
||||||
|
scheduler.Record([this, dst_region, src_region, pipeline, layout, sampler, src_depth_view,
|
||||||
|
src_stencil_view, resolve_stencil](vk::CommandBuffer cmdbuf) {
|
||||||
|
if (resolve_stencil) {
|
||||||
|
const VkDescriptorSet descriptor_set = two_textures_descriptor_allocator.Commit();
|
||||||
|
UpdateTwoTexturesDescriptorSet(device, descriptor_set, sampler, src_depth_view,
|
||||||
|
src_stencil_view);
|
||||||
|
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptor_set,
|
||||||
|
nullptr);
|
||||||
|
} else {
|
||||||
|
const VkDescriptorSet descriptor_set = one_texture_descriptor_allocator.Commit();
|
||||||
|
UpdateOneTextureDescriptorSet(device, descriptor_set, sampler, src_depth_view);
|
||||||
|
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptor_set,
|
||||||
|
nullptr);
|
||||||
|
}
|
||||||
|
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
||||||
|
BindBlitState(cmdbuf, layout, dst_region, src_region);
|
||||||
|
cmdbuf.Draw(3, 1, 0, 0);
|
||||||
|
});
|
||||||
|
scheduler.InvalidateState();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlitImageHelper::BlitDepthStencil(const Framebuffer* dst_framebuffer,
|
void BlitImageHelper::BlitDepthStencil(const Framebuffer* dst_framebuffer,
|
||||||
@@ -791,23 +739,35 @@ void BlitImageHelper::BlitDepthStencil(const Framebuffer* dst_framebuffer,
|
|||||||
const Region2D& dst_region, const Region2D& src_region,
|
const Region2D& dst_region, const Region2D& src_region,
|
||||||
Tegra::Engines::Fermi2D::Filter filter,
|
Tegra::Engines::Fermi2D::Filter filter,
|
||||||
Tegra::Engines::Fermi2D::Operation operation) {
|
Tegra::Engines::Fermi2D::Operation operation) {
|
||||||
|
if (!device.IsExtShaderStencilExportSupported()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
ASSERT(filter == Tegra::Engines::Fermi2D::Filter::Point);
|
ASSERT(filter == Tegra::Engines::Fermi2D::Filter::Point);
|
||||||
ASSERT(operation == Tegra::Engines::Fermi2D::Operation::SrcCopy);
|
ASSERT(operation == Tegra::Engines::Fermi2D::Operation::SrcCopy);
|
||||||
const bool blit_stencil = device.IsExtShaderStencilExportSupported();
|
|
||||||
const BlitImagePipelineKey key{
|
const BlitImagePipelineKey key{
|
||||||
.renderpass = dst_framebuffer->RenderPass(),
|
.renderpass = dst_framebuffer->RenderPass(),
|
||||||
.operation = operation,
|
.operation = operation,
|
||||||
};
|
};
|
||||||
VkPipeline pipeline{};
|
const VkPipelineLayout layout = *two_textures_pipeline_layout;
|
||||||
VkImageView src_stencil_view = VK_NULL_HANDLE;
|
const VkSampler sampler = *nearest_sampler;
|
||||||
if (blit_stencil) {
|
const VkPipeline pipeline = FindOrEmplaceDepthStencilPipeline(key);
|
||||||
pipeline = FindOrEmplaceDepthStencilPipeline(key);
|
const VkImageView src_depth_view = src_image_view.DepthView();
|
||||||
src_stencil_view = src_image_view.StencilView();
|
const VkImageView src_stencil_view = src_image_view.StencilView();
|
||||||
} else {
|
|
||||||
pipeline = FindOrEmplaceBlitDepthPipeline(key.renderpass);
|
RecordShaderReadBarrier(scheduler, src_image_view);
|
||||||
}
|
scheduler.RequestRenderpass(dst_framebuffer);
|
||||||
BlitImpl(dst_framebuffer, src_image_view, dst_region, src_region, pipeline, *nearest_sampler,
|
scheduler.Record([dst_region, src_region, pipeline, layout, sampler, src_depth_view,
|
||||||
src_image_view.DepthView(), src_stencil_view, blit_stencil);
|
src_stencil_view, this](vk::CommandBuffer cmdbuf) {
|
||||||
|
const VkDescriptorSet descriptor_set = two_textures_descriptor_allocator.Commit();
|
||||||
|
UpdateTwoTexturesDescriptorSet(device, descriptor_set, sampler, src_depth_view,
|
||||||
|
src_stencil_view);
|
||||||
|
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
||||||
|
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptor_set,
|
||||||
|
nullptr);
|
||||||
|
BindBlitState(cmdbuf, layout, dst_region, src_region);
|
||||||
|
cmdbuf.Draw(3, 1, 0, 0);
|
||||||
|
});
|
||||||
|
scheduler.InvalidateState();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlitImageHelper::ConvertD32ToR32(const Framebuffer* dst_framebuffer,
|
void BlitImageHelper::ConvertD32ToR32(const Framebuffer* dst_framebuffer,
|
||||||
@@ -922,183 +882,19 @@ void BlitImageHelper::ClearDepthStencil(const Framebuffer* dst_framebuffer, bool
|
|||||||
scheduler.InvalidateState();
|
scheduler.InvalidateState();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlitImageHelper::CopyMSAAImpl(VkRenderPass renderpass, VkPipeline pipeline,
|
|
||||||
VkPipelineLayout layout, VkImage dst_image,
|
|
||||||
VkFormat dst_vk_format, VkImage src_image,
|
|
||||||
VkFormat src_vk_format, s32 scale_x, s32 scale_y,
|
|
||||||
std::span<const VideoCommon::ImageCopy> copies,
|
|
||||||
const MSAACopyAspectInfo& aspect_info, bool copy_stencil) {
|
|
||||||
while (!msaa_copy_resources.empty() && scheduler.IsFree(msaa_copy_resources.front().tick)) {
|
|
||||||
msaa_copy_resources.pop_front();
|
|
||||||
}
|
|
||||||
const VkSampler sampler = *nearest_sampler;
|
|
||||||
for (const VideoCommon::ImageCopy& copy : copies) {
|
|
||||||
const s32 num_layers = (std::min)(copy.src_subresource.num_layers,
|
|
||||||
copy.dst_subresource.num_layers);
|
|
||||||
for (s32 layer = 0; layer < num_layers; ++layer) {
|
|
||||||
const u32 src_level = static_cast<u32>(copy.src_subresource.base_level);
|
|
||||||
const u32 src_layer = static_cast<u32>(copy.src_subresource.base_layer + layer);
|
|
||||||
vk::ImageView src_view =
|
|
||||||
MakeMSAACopyView(device.GetLogical(), src_image, src_vk_format, src_level,
|
|
||||||
src_layer, aspect_info.src_view_aspect);
|
|
||||||
vk::ImageView src_stencil_view;
|
|
||||||
if (copy_stencil) {
|
|
||||||
src_stencil_view =
|
|
||||||
MakeMSAACopyView(device.GetLogical(), src_image, src_vk_format, src_level,
|
|
||||||
src_layer, VK_IMAGE_ASPECT_STENCIL_BIT);
|
|
||||||
}
|
|
||||||
vk::ImageView dst_view =
|
|
||||||
MakeMSAACopyView(device.GetLogical(), dst_image, dst_vk_format,
|
|
||||||
static_cast<u32>(copy.dst_subresource.base_level),
|
|
||||||
static_cast<u32>(copy.dst_subresource.base_layer + layer),
|
|
||||||
aspect_info.attachment_aspect);
|
|
||||||
const VkOffset2D dst_offset{copy.dst_offset.x, copy.dst_offset.y};
|
|
||||||
const VkExtent2D dst_extent{copy.extent.width, copy.extent.height};
|
|
||||||
const VkRect2D render_area{
|
|
||||||
.offset = dst_offset,
|
|
||||||
.extent = dst_extent,
|
|
||||||
};
|
|
||||||
vk::Framebuffer framebuffer = device.GetLogical().CreateFramebuffer(VkFramebufferCreateInfo{
|
|
||||||
.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.flags = 0,
|
|
||||||
.renderPass = renderpass,
|
|
||||||
.attachmentCount = 1,
|
|
||||||
.pAttachments = dst_view.address(),
|
|
||||||
.width = static_cast<u32>(dst_offset.x) + dst_extent.width,
|
|
||||||
.height = static_cast<u32>(dst_offset.y) + dst_extent.height,
|
|
||||||
.layers = 1,
|
|
||||||
});
|
|
||||||
const MSAACopyPushConstants push_constants{
|
|
||||||
.dst_offset = {dst_offset.x, dst_offset.y},
|
|
||||||
.src_offset = {copy.src_offset.x, copy.src_offset.y},
|
|
||||||
.scale = {scale_x, scale_y},
|
|
||||||
};
|
|
||||||
VkImageView src_stencil_handle = VK_NULL_HANDLE;
|
|
||||||
if (copy_stencil) {
|
|
||||||
src_stencil_handle = *src_stencil_view;
|
|
||||||
}
|
|
||||||
scheduler.RequestOutsideRenderPassOperationContext();
|
|
||||||
scheduler.Record([this, pipeline, layout, sampler, renderpass,
|
|
||||||
framebuffer_handle = *framebuffer, src_view_handle = *src_view,
|
|
||||||
src_stencil_handle, src = src_image, dst = dst_image, render_area,
|
|
||||||
aspect_info, push_constants](vk::CommandBuffer cmdbuf) {
|
|
||||||
const VkImageSubresourceRange barrier_range{
|
|
||||||
.aspectMask = aspect_info.barrier_aspect,
|
|
||||||
.baseMipLevel = 0,
|
|
||||||
.levelCount = VK_REMAINING_MIP_LEVELS,
|
|
||||||
.baseArrayLayer = 0,
|
|
||||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
|
||||||
};
|
|
||||||
const std::array pre_barriers{
|
|
||||||
VkImageMemoryBarrier{
|
|
||||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.srcAccessMask = aspect_info.pre_src_access,
|
|
||||||
.dstAccessMask = aspect_info.pre_src_dst_access,
|
|
||||||
.oldLayout = VK_IMAGE_LAYOUT_GENERAL,
|
|
||||||
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
|
|
||||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
|
||||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
|
||||||
.image = src,
|
|
||||||
.subresourceRange = barrier_range,
|
|
||||||
},
|
|
||||||
VkImageMemoryBarrier{
|
|
||||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.srcAccessMask = aspect_info.pre_src_access,
|
|
||||||
.dstAccessMask = aspect_info.pre_dst_dst_access,
|
|
||||||
.oldLayout = VK_IMAGE_LAYOUT_GENERAL,
|
|
||||||
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
|
|
||||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
|
||||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
|
||||||
.image = dst,
|
|
||||||
.subresourceRange = barrier_range,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
cmdbuf.PipelineBarrier(aspect_info.pre_src_stages, aspect_info.pre_dst_stages, 0,
|
|
||||||
nullptr, nullptr, pre_barriers);
|
|
||||||
const VkRenderPassBeginInfo renderpass_bi{
|
|
||||||
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.renderPass = renderpass,
|
|
||||||
.framebuffer = framebuffer_handle,
|
|
||||||
.renderArea = render_area,
|
|
||||||
.clearValueCount = 0,
|
|
||||||
.pClearValues = nullptr,
|
|
||||||
};
|
|
||||||
cmdbuf.BeginRenderPass(renderpass_bi, VK_SUBPASS_CONTENTS_INLINE);
|
|
||||||
VkDescriptorSet descriptor_set = VK_NULL_HANDLE;
|
|
||||||
if (src_stencil_handle != VK_NULL_HANDLE) {
|
|
||||||
descriptor_set = two_textures_descriptor_allocator.Commit();
|
|
||||||
UpdateTwoTexturesDescriptorSet(device, descriptor_set, sampler, src_view_handle,
|
|
||||||
src_stencil_handle);
|
|
||||||
} else {
|
|
||||||
descriptor_set = one_texture_descriptor_allocator.Commit();
|
|
||||||
UpdateOneTextureDescriptorSet(device, descriptor_set, sampler, src_view_handle);
|
|
||||||
}
|
|
||||||
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
|
||||||
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptor_set,
|
|
||||||
nullptr);
|
|
||||||
const VkViewport viewport{
|
|
||||||
.x = static_cast<float>(render_area.offset.x),
|
|
||||||
.y = static_cast<float>(render_area.offset.y),
|
|
||||||
.width = static_cast<float>(render_area.extent.width),
|
|
||||||
.height = static_cast<float>(render_area.extent.height),
|
|
||||||
.minDepth = 0.0f,
|
|
||||||
.maxDepth = 1.0f,
|
|
||||||
};
|
|
||||||
cmdbuf.SetViewport(0, viewport);
|
|
||||||
cmdbuf.SetScissor(0, render_area);
|
|
||||||
cmdbuf.PushConstants(layout, VK_SHADER_STAGE_FRAGMENT_BIT, push_constants);
|
|
||||||
cmdbuf.Draw(3, 1, 0, 0);
|
|
||||||
cmdbuf.EndRenderPass();
|
|
||||||
const VkImageMemoryBarrier post_barrier{
|
|
||||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.srcAccessMask = aspect_info.post_src_access,
|
|
||||||
.dstAccessMask = aspect_info.post_dst_access,
|
|
||||||
.oldLayout = VK_IMAGE_LAYOUT_GENERAL,
|
|
||||||
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
|
|
||||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
|
||||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
|
||||||
.image = dst,
|
|
||||||
.subresourceRange = barrier_range,
|
|
||||||
};
|
|
||||||
cmdbuf.PipelineBarrier(aspect_info.post_src_stages, aspect_info.post_dst_stages, 0,
|
|
||||||
post_barrier);
|
|
||||||
});
|
|
||||||
msaa_copy_resources.push_back(MSAACopyResources{
|
|
||||||
.tick = scheduler.CurrentTick(),
|
|
||||||
.src_view = std::move(src_view),
|
|
||||||
.dst_view = std::move(dst_view),
|
|
||||||
.framebuffer = std::move(framebuffer),
|
|
||||||
});
|
|
||||||
if (copy_stencil) {
|
|
||||||
msaa_copy_resources.push_back(MSAACopyResources{
|
|
||||||
.tick = scheduler.CurrentTick(),
|
|
||||||
.src_view = std::move(src_stencil_view),
|
|
||||||
.dst_view = vk::ImageView{},
|
|
||||||
.framebuffer = vk::Framebuffer{},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
scheduler.InvalidateState();
|
|
||||||
}
|
|
||||||
|
|
||||||
void BlitImageHelper::CopyMSAA(RenderPassCache& render_pass_cache, VkImage dst_image,
|
void BlitImageHelper::CopyMSAA(RenderPassCache& render_pass_cache, VkImage dst_image,
|
||||||
VideoCore::Surface::PixelFormat dst_format, VkImage src_image,
|
VideoCore::Surface::PixelFormat dst_format, VkImage src_image,
|
||||||
VideoCore::Surface::PixelFormat src_format, u32 num_samples,
|
VideoCore::Surface::PixelFormat src_format, u32 num_samples,
|
||||||
std::span<const VideoCommon::ImageCopy> copies,
|
std::span<const VideoCommon::ImageCopy> copies,
|
||||||
bool msaa_to_non_msaa) {
|
bool msaa_to_non_msaa) {
|
||||||
|
while (!msaa_copy_resources.empty() && scheduler.IsFree(msaa_copy_resources.front().tick)) {
|
||||||
|
msaa_copy_resources.pop_front();
|
||||||
|
}
|
||||||
const auto [samples_x, samples_y] = VideoCommon::SamplesLog2(static_cast<int>(num_samples));
|
const auto [samples_x, samples_y] = VideoCommon::SamplesLog2(static_cast<int>(num_samples));
|
||||||
const s32 scale_x = 1 << samples_x;
|
const s32 scale_x = 1 << samples_x;
|
||||||
const s32 scale_y = 1 << samples_y;
|
const s32 scale_y = 1 << samples_y;
|
||||||
VkSampleCountFlagBits samples = SampleCountFlag(num_samples);
|
const VkSampleCountFlagBits samples =
|
||||||
if (msaa_to_non_msaa) {
|
msaa_to_non_msaa ? VK_SAMPLE_COUNT_1_BIT : SampleCountFlag(num_samples);
|
||||||
samples = VK_SAMPLE_COUNT_1_BIT;
|
|
||||||
}
|
|
||||||
RenderPassKey renderpass_key{};
|
RenderPassKey renderpass_key{};
|
||||||
renderpass_key.color_formats.fill(VideoCore::Surface::PixelFormat::Invalid);
|
renderpass_key.color_formats.fill(VideoCore::Surface::PixelFormat::Invalid);
|
||||||
renderpass_key.color_formats[0] = dst_format;
|
renderpass_key.color_formats[0] = dst_format;
|
||||||
@@ -1109,35 +905,149 @@ void BlitImageHelper::CopyMSAA(RenderPassCache& render_pass_cache, VkImage dst_i
|
|||||||
.renderpass = renderpass,
|
.renderpass = renderpass,
|
||||||
.samples = samples,
|
.samples = samples,
|
||||||
.msaa_to_non_msaa = msaa_to_non_msaa,
|
.msaa_to_non_msaa = msaa_to_non_msaa,
|
||||||
.format_class = FormatClass(dst_format),
|
|
||||||
};
|
|
||||||
const MSAACopyAspectInfo aspect_info{
|
|
||||||
.src_view_aspect = VK_IMAGE_ASPECT_COLOR_BIT,
|
|
||||||
.attachment_aspect = VK_IMAGE_ASPECT_COLOR_BIT,
|
|
||||||
.barrier_aspect = VK_IMAGE_ASPECT_COLOR_BIT,
|
|
||||||
.pre_src_access = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_WRITE_BIT |
|
|
||||||
VK_ACCESS_TRANSFER_WRITE_BIT,
|
|
||||||
.pre_src_dst_access = VK_ACCESS_SHADER_READ_BIT,
|
|
||||||
.pre_dst_dst_access =
|
|
||||||
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
|
||||||
.pre_src_stages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
|
|
||||||
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
|
|
||||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT,
|
|
||||||
.pre_dst_stages =
|
|
||||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
|
||||||
.post_src_access = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
|
||||||
.post_dst_access = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_TRANSFER_READ_BIT,
|
|
||||||
.post_src_stages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
|
||||||
.post_dst_stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
|
||||||
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT,
|
|
||||||
};
|
};
|
||||||
|
const VkPipeline pipeline = FindOrEmplaceMSAACopyPipeline(key);
|
||||||
|
const VkPipelineLayout layout = *msaa_copy_pipeline_layout;
|
||||||
|
const VkSampler sampler = *nearest_sampler;
|
||||||
const VkFormat src_vk_format =
|
const VkFormat src_vk_format =
|
||||||
MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, true, src_format).format;
|
MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, true, src_format).format;
|
||||||
const VkFormat dst_vk_format =
|
const VkFormat dst_vk_format =
|
||||||
MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, true, dst_format).format;
|
MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, true, dst_format).format;
|
||||||
CopyMSAAImpl(renderpass, FindOrEmplaceMSAACopyPipeline(key), *msaa_copy_pipeline_layout,
|
for (const VideoCommon::ImageCopy& copy : copies) {
|
||||||
dst_image, dst_vk_format, src_image, src_vk_format, scale_x, scale_y, copies,
|
ASSERT(copy.src_subresource.base_layer == 0);
|
||||||
aspect_info, false);
|
ASSERT(copy.src_subresource.num_layers == 1);
|
||||||
|
ASSERT(copy.dst_subresource.base_layer == 0);
|
||||||
|
ASSERT(copy.dst_subresource.num_layers == 1);
|
||||||
|
vk::ImageView src_view =
|
||||||
|
MakeMSAACopyView(device.GetLogical(), src_image, src_vk_format,
|
||||||
|
static_cast<u32>(copy.src_subresource.base_level));
|
||||||
|
vk::ImageView dst_view =
|
||||||
|
MakeMSAACopyView(device.GetLogical(), dst_image, dst_vk_format,
|
||||||
|
static_cast<u32>(copy.dst_subresource.base_level));
|
||||||
|
const VkOffset2D dst_offset{copy.dst_offset.x, copy.dst_offset.y};
|
||||||
|
const VkExtent2D dst_extent{copy.extent.width, copy.extent.height};
|
||||||
|
const VkRect2D render_area{
|
||||||
|
.offset = dst_offset,
|
||||||
|
.extent = dst_extent,
|
||||||
|
};
|
||||||
|
vk::Framebuffer framebuffer = device.GetLogical().CreateFramebuffer(VkFramebufferCreateInfo{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.flags = 0,
|
||||||
|
.renderPass = renderpass,
|
||||||
|
.attachmentCount = 1,
|
||||||
|
.pAttachments = dst_view.address(),
|
||||||
|
.width = static_cast<u32>(dst_offset.x) + dst_extent.width,
|
||||||
|
.height = static_cast<u32>(dst_offset.y) + dst_extent.height,
|
||||||
|
.layers = 1,
|
||||||
|
});
|
||||||
|
const MSAACopyPushConstants push_constants{
|
||||||
|
.dst_offset = {dst_offset.x, dst_offset.y},
|
||||||
|
.src_offset = {copy.src_offset.x, copy.src_offset.y},
|
||||||
|
.scale = {scale_x, scale_y},
|
||||||
|
};
|
||||||
|
scheduler.RequestOutsideRenderPassOperationContext();
|
||||||
|
scheduler.Record([this, pipeline, layout, sampler, renderpass,
|
||||||
|
framebuffer_handle = *framebuffer, src_view_handle = *src_view,
|
||||||
|
src = src_image, dst = dst_image, render_area,
|
||||||
|
push_constants](vk::CommandBuffer cmdbuf) {
|
||||||
|
constexpr VkImageSubresourceRange color_range{
|
||||||
|
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
|
.baseMipLevel = 0,
|
||||||
|
.levelCount = VK_REMAINING_MIP_LEVELS,
|
||||||
|
.baseArrayLayer = 0,
|
||||||
|
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||||
|
};
|
||||||
|
const std::array pre_barriers{
|
||||||
|
VkImageMemoryBarrier{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
|
||||||
|
VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||||
|
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT,
|
||||||
|
.oldLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||||
|
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||||
|
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
|
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
|
.image = src,
|
||||||
|
.subresourceRange = color_range,
|
||||||
|
},
|
||||||
|
VkImageMemoryBarrier{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
|
||||||
|
VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||||
|
.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
|
||||||
|
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||||
|
.oldLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||||
|
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||||
|
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
|
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
|
.image = dst,
|
||||||
|
.subresourceRange = color_range,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||||
|
0, nullptr, nullptr, pre_barriers);
|
||||||
|
const VkRenderPassBeginInfo renderpass_bi{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.renderPass = renderpass,
|
||||||
|
.framebuffer = framebuffer_handle,
|
||||||
|
.renderArea = render_area,
|
||||||
|
.clearValueCount = 0,
|
||||||
|
.pClearValues = nullptr,
|
||||||
|
};
|
||||||
|
cmdbuf.BeginRenderPass(renderpass_bi, VK_SUBPASS_CONTENTS_INLINE);
|
||||||
|
const VkDescriptorSet descriptor_set = one_texture_descriptor_allocator.Commit();
|
||||||
|
UpdateOneTextureDescriptorSet(device, descriptor_set, sampler, src_view_handle);
|
||||||
|
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
||||||
|
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptor_set,
|
||||||
|
nullptr);
|
||||||
|
const VkViewport viewport{
|
||||||
|
.x = static_cast<float>(render_area.offset.x),
|
||||||
|
.y = static_cast<float>(render_area.offset.y),
|
||||||
|
.width = static_cast<float>(render_area.extent.width),
|
||||||
|
.height = static_cast<float>(render_area.extent.height),
|
||||||
|
.minDepth = 0.0f,
|
||||||
|
.maxDepth = 1.0f,
|
||||||
|
};
|
||||||
|
cmdbuf.SetViewport(0, viewport);
|
||||||
|
cmdbuf.SetScissor(0, render_area);
|
||||||
|
cmdbuf.PushConstants(layout, VK_SHADER_STAGE_FRAGMENT_BIT, push_constants);
|
||||||
|
cmdbuf.Draw(3, 1, 0, 0);
|
||||||
|
cmdbuf.EndRenderPass();
|
||||||
|
const VkImageMemoryBarrier post_barrier{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||||
|
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_TRANSFER_READ_BIT,
|
||||||
|
.oldLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||||
|
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||||
|
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
|
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
|
.image = dst,
|
||||||
|
.subresourceRange = color_range,
|
||||||
|
};
|
||||||
|
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||||
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
|
0, post_barrier);
|
||||||
|
});
|
||||||
|
msaa_copy_resources.push_back(MSAACopyResources{
|
||||||
|
.tick = scheduler.CurrentTick(),
|
||||||
|
.src_view = std::move(src_view),
|
||||||
|
.dst_view = std::move(dst_view),
|
||||||
|
.framebuffer = std::move(framebuffer),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
scheduler.InvalidateState();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlitImageHelper::Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
|
void BlitImageHelper::Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
|
||||||
@@ -1469,87 +1379,6 @@ VkPipeline BlitImageHelper::FindOrEmplaceBlitColorMSAAPipeline(const BlitMSAAPip
|
|||||||
return *blit_msaa_color_pipelines.back();
|
return *blit_msaa_color_pipelines.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
VkPipeline BlitImageHelper::FindOrEmplaceBlitDepthStencilMSAAPipeline(
|
|
||||||
const BlitMSAAPipelineKey& key, bool blit_stencil) {
|
|
||||||
auto& keys = blit_stencil ? blit_msaa_depth_stencil_keys : blit_msaa_depth_keys;
|
|
||||||
auto& pipelines = blit_stencil ? blit_msaa_depth_stencil_pipelines : blit_msaa_depth_pipelines;
|
|
||||||
const auto it = std::ranges::find(keys, key);
|
|
||||||
if (it != keys.end()) {
|
|
||||||
return *pipelines[std::distance(keys.begin(), it)];
|
|
||||||
}
|
|
||||||
keys.push_back(key);
|
|
||||||
const std::array stages =
|
|
||||||
MakeStages(*full_screen_vert,
|
|
||||||
blit_stencil ? *blit_depth_stencil_msaa_frag : *blit_depth_msaa_frag);
|
|
||||||
const VkPipelineMultisampleStateCreateInfo multisample_ci{
|
|
||||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.flags = 0,
|
|
||||||
.rasterizationSamples = key.samples,
|
|
||||||
.sampleShadingEnable = VK_TRUE,
|
|
||||||
.minSampleShading = 1.0f,
|
|
||||||
.pSampleMask = nullptr,
|
|
||||||
.alphaToCoverageEnable = VK_FALSE,
|
|
||||||
.alphaToOneEnable = VK_FALSE,
|
|
||||||
};
|
|
||||||
const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device);
|
|
||||||
pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({
|
|
||||||
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.flags = 0,
|
|
||||||
.stageCount = static_cast<u32>(stages.size()),
|
|
||||||
.pStages = stages.data(),
|
|
||||||
.pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
|
||||||
.pInputAssemblyState = &input_assembly_ci,
|
|
||||||
.pTessellationState = nullptr,
|
|
||||||
.pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO,
|
|
||||||
.pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
|
|
||||||
.pMultisampleState = &multisample_ci,
|
|
||||||
.pDepthStencilState = blit_stencil ? &PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO
|
|
||||||
: &PIPELINE_DEPTH_ONLY_STATE_CREATE_INFO,
|
|
||||||
.pColorBlendState = &PIPELINE_COLOR_BLEND_STATE_EMPTY_CREATE_INFO,
|
|
||||||
.pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO,
|
|
||||||
.layout = blit_stencil ? *two_textures_pipeline_layout : *one_texture_pipeline_layout,
|
|
||||||
.renderPass = key.renderpass,
|
|
||||||
.subpass = 0,
|
|
||||||
.basePipelineHandle = VK_NULL_HANDLE,
|
|
||||||
.basePipelineIndex = 0,
|
|
||||||
}));
|
|
||||||
return *pipelines.back();
|
|
||||||
}
|
|
||||||
|
|
||||||
VkPipeline BlitImageHelper::FindOrEmplaceBlitDepthPipeline(VkRenderPass renderpass) {
|
|
||||||
const auto it = std::ranges::find(blit_depth_keys, renderpass);
|
|
||||||
if (it != blit_depth_keys.end()) {
|
|
||||||
return *blit_depth_pipelines[std::distance(blit_depth_keys.begin(), it)];
|
|
||||||
}
|
|
||||||
blit_depth_keys.push_back(renderpass);
|
|
||||||
const std::array stages = MakeStages(*full_screen_vert, *blit_depth_frag);
|
|
||||||
const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device);
|
|
||||||
blit_depth_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({
|
|
||||||
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.flags = 0,
|
|
||||||
.stageCount = static_cast<u32>(stages.size()),
|
|
||||||
.pStages = stages.data(),
|
|
||||||
.pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
|
||||||
.pInputAssemblyState = &input_assembly_ci,
|
|
||||||
.pTessellationState = nullptr,
|
|
||||||
.pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO,
|
|
||||||
.pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
|
|
||||||
.pMultisampleState = &PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
|
|
||||||
.pDepthStencilState = &PIPELINE_DEPTH_ONLY_STATE_CREATE_INFO,
|
|
||||||
.pColorBlendState = &PIPELINE_COLOR_BLEND_STATE_EMPTY_CREATE_INFO,
|
|
||||||
.pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO,
|
|
||||||
.layout = *one_texture_pipeline_layout,
|
|
||||||
.renderPass = renderpass,
|
|
||||||
.subpass = 0,
|
|
||||||
.basePipelineHandle = VK_NULL_HANDLE,
|
|
||||||
.basePipelineIndex = 0,
|
|
||||||
}));
|
|
||||||
return *blit_depth_pipelines.back();
|
|
||||||
}
|
|
||||||
|
|
||||||
VkPipeline BlitImageHelper::FindOrEmplaceResolveDepthStencilPipeline(VkRenderPass renderpass,
|
VkPipeline BlitImageHelper::FindOrEmplaceResolveDepthStencilPipeline(VkRenderPass renderpass,
|
||||||
bool resolve_stencil) {
|
bool resolve_stencil) {
|
||||||
auto& keys = resolve_stencil ? resolve_depth_stencil_keys : resolve_depth_keys;
|
auto& keys = resolve_stencil ? resolve_depth_stencil_keys : resolve_depth_keys;
|
||||||
@@ -1588,83 +1417,15 @@ VkPipeline BlitImageHelper::FindOrEmplaceResolveDepthStencilPipeline(VkRenderPas
|
|||||||
return *pipelines.back();
|
return *pipelines.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlitImageHelper::CopyMSAADepth(RenderPassCache& render_pass_cache, VkImage dst_image,
|
|
||||||
VideoCore::Surface::PixelFormat dst_format, VkImage src_image,
|
|
||||||
VideoCore::Surface::PixelFormat src_format, u32 num_samples,
|
|
||||||
std::span<const VideoCommon::ImageCopy> copies,
|
|
||||||
bool copy_stencil, bool msaa_to_non_msaa) {
|
|
||||||
const auto [samples_x, samples_y] = VideoCommon::SamplesLog2(static_cast<int>(num_samples));
|
|
||||||
const s32 scale_x = 1 << samples_x;
|
|
||||||
const s32 scale_y = 1 << samples_y;
|
|
||||||
VkSampleCountFlagBits samples = SampleCountFlag(num_samples);
|
|
||||||
if (msaa_to_non_msaa) {
|
|
||||||
samples = VK_SAMPLE_COUNT_1_BIT;
|
|
||||||
}
|
|
||||||
RenderPassKey renderpass_key{};
|
|
||||||
renderpass_key.color_formats.fill(VideoCore::Surface::PixelFormat::Invalid);
|
|
||||||
renderpass_key.depth_format = dst_format;
|
|
||||||
renderpass_key.samples = samples;
|
|
||||||
const VkRenderPass renderpass = render_pass_cache.Get(renderpass_key);
|
|
||||||
const MSAACopyPipelineKey key{
|
|
||||||
.renderpass = renderpass,
|
|
||||||
.samples = samples,
|
|
||||||
.msaa_to_non_msaa = msaa_to_non_msaa,
|
|
||||||
.format_class = MSAACopyFormatClass::Float,
|
|
||||||
};
|
|
||||||
VkImageAspectFlags attachment_aspect = VK_IMAGE_ASPECT_DEPTH_BIT;
|
|
||||||
if (VideoCore::Surface::GetFormatType(dst_format) ==
|
|
||||||
VideoCore::Surface::SurfaceType::DepthStencil) {
|
|
||||||
attachment_aspect |= VK_IMAGE_ASPECT_STENCIL_BIT;
|
|
||||||
}
|
|
||||||
VkPipelineLayout layout = *msaa_copy_pipeline_layout;
|
|
||||||
if (copy_stencil) {
|
|
||||||
layout = *msaa_copy_depth_stencil_pipeline_layout;
|
|
||||||
}
|
|
||||||
const MSAACopyAspectInfo aspect_info{
|
|
||||||
.src_view_aspect = VK_IMAGE_ASPECT_DEPTH_BIT,
|
|
||||||
.attachment_aspect = attachment_aspect,
|
|
||||||
.barrier_aspect = attachment_aspect,
|
|
||||||
.pre_src_access =
|
|
||||||
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT,
|
|
||||||
.pre_src_dst_access = VK_ACCESS_SHADER_READ_BIT,
|
|
||||||
.pre_dst_dst_access = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
|
|
||||||
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
|
|
||||||
.pre_src_stages = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
|
|
||||||
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT |
|
|
||||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
|
||||||
.pre_dst_stages =
|
|
||||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,
|
|
||||||
.post_src_access = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
|
|
||||||
.post_dst_access = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_TRANSFER_READ_BIT |
|
|
||||||
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
|
|
||||||
.post_src_stages = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
|
|
||||||
.post_dst_stages = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER,
|
|
||||||
};
|
|
||||||
const VkFormat src_vk_format =
|
|
||||||
MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, true, src_format).format;
|
|
||||||
const VkFormat dst_vk_format =
|
|
||||||
MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, true, dst_format).format;
|
|
||||||
CopyMSAAImpl(renderpass, FindOrEmplaceMSAACopyDepthPipeline(key, copy_stencil), layout,
|
|
||||||
dst_image, dst_vk_format, src_image, src_vk_format, scale_x, scale_y, copies,
|
|
||||||
aspect_info, copy_stencil);
|
|
||||||
}
|
|
||||||
|
|
||||||
VkPipeline BlitImageHelper::FindOrEmplaceMSAACopyPipeline(const MSAACopyPipelineKey& key) {
|
VkPipeline BlitImageHelper::FindOrEmplaceMSAACopyPipeline(const MSAACopyPipelineKey& key) {
|
||||||
const auto it = std::ranges::find(msaa_copy_keys, key);
|
const auto it = std::ranges::find(msaa_copy_keys, key);
|
||||||
if (it != msaa_copy_keys.end()) {
|
if (it != msaa_copy_keys.end()) {
|
||||||
return *msaa_copy_pipelines[std::distance(msaa_copy_keys.begin(), it)];
|
return *msaa_copy_pipelines[std::distance(msaa_copy_keys.begin(), it)];
|
||||||
}
|
}
|
||||||
msaa_copy_keys.push_back(key);
|
msaa_copy_keys.push_back(key);
|
||||||
VkShaderModule frag_module = key.msaa_to_non_msaa ? *convert_msaa_to_non_msaa_frag
|
const std::array stages = MakeStages(*clear_color_vert, key.msaa_to_non_msaa
|
||||||
: *convert_non_msaa_to_msaa_frag;
|
? *convert_msaa_to_non_msaa_frag
|
||||||
if (key.format_class == MSAACopyFormatClass::SignedInteger) {
|
: *convert_non_msaa_to_msaa_frag);
|
||||||
frag_module = key.msaa_to_non_msaa ? *convert_msaa_to_non_msaa_sint_frag
|
|
||||||
: *convert_non_msaa_to_msaa_sint_frag;
|
|
||||||
} else if (key.format_class == MSAACopyFormatClass::UnsignedInteger) {
|
|
||||||
frag_module = key.msaa_to_non_msaa ? *convert_msaa_to_non_msaa_uint_frag
|
|
||||||
: *convert_non_msaa_to_msaa_uint_frag;
|
|
||||||
}
|
|
||||||
const std::array stages = MakeStages(*clear_color_vert, frag_module);
|
|
||||||
const VkPipelineMultisampleStateCreateInfo multisample_ci{
|
const VkPipelineMultisampleStateCreateInfo multisample_ci{
|
||||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
@@ -1701,85 +1462,6 @@ VkPipeline BlitImageHelper::FindOrEmplaceMSAACopyPipeline(const MSAACopyPipeline
|
|||||||
return *msaa_copy_pipelines.back();
|
return *msaa_copy_pipelines.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
VkPipeline BlitImageHelper::FindOrEmplaceMSAACopyDepthPipeline(const MSAACopyPipelineKey& key,
|
|
||||||
bool copy_stencil) {
|
|
||||||
auto& keys = copy_stencil ? msaa_copy_depth_stencil_keys : msaa_copy_depth_keys;
|
|
||||||
auto& pipelines = copy_stencil ? msaa_copy_depth_stencil_pipelines : msaa_copy_depth_pipelines;
|
|
||||||
const auto it = std::ranges::find(keys, key);
|
|
||||||
if (it != keys.end()) {
|
|
||||||
return *pipelines[std::distance(keys.begin(), it)];
|
|
||||||
}
|
|
||||||
keys.push_back(key);
|
|
||||||
VkShaderModule frag_module;
|
|
||||||
if (key.msaa_to_non_msaa) {
|
|
||||||
frag_module = copy_stencil ? *convert_msaa_to_non_msaa_depth_stencil_frag
|
|
||||||
: *convert_msaa_to_non_msaa_depth_frag;
|
|
||||||
} else {
|
|
||||||
frag_module = copy_stencil ? *convert_non_msaa_to_msaa_depth_stencil_frag
|
|
||||||
: *convert_non_msaa_to_msaa_depth_frag;
|
|
||||||
}
|
|
||||||
const std::array stages = MakeStages(*clear_color_vert, frag_module);
|
|
||||||
const VkPipelineMultisampleStateCreateInfo multisample_ci{
|
|
||||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.flags = 0,
|
|
||||||
.rasterizationSamples = key.samples,
|
|
||||||
.sampleShadingEnable = key.msaa_to_non_msaa ? VK_FALSE : VK_TRUE,
|
|
||||||
.minSampleShading = key.msaa_to_non_msaa ? 0.0f : 1.0f,
|
|
||||||
.pSampleMask = nullptr,
|
|
||||||
.alphaToCoverageEnable = VK_FALSE,
|
|
||||||
.alphaToOneEnable = VK_FALSE,
|
|
||||||
};
|
|
||||||
static constexpr VkStencilOpState REPLACE_STENCIL_OP{
|
|
||||||
.failOp = VK_STENCIL_OP_REPLACE,
|
|
||||||
.passOp = VK_STENCIL_OP_REPLACE,
|
|
||||||
.depthFailOp = VK_STENCIL_OP_REPLACE,
|
|
||||||
.compareOp = VK_COMPARE_OP_ALWAYS,
|
|
||||||
.compareMask = 0xFF,
|
|
||||||
.writeMask = 0xFF,
|
|
||||||
.reference = 0,
|
|
||||||
};
|
|
||||||
const VkPipelineDepthStencilStateCreateInfo depth_stencil_ci{
|
|
||||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.flags = 0,
|
|
||||||
.depthTestEnable = VK_TRUE,
|
|
||||||
.depthWriteEnable = VK_TRUE,
|
|
||||||
.depthCompareOp = VK_COMPARE_OP_ALWAYS,
|
|
||||||
.depthBoundsTestEnable = VK_FALSE,
|
|
||||||
.stencilTestEnable = copy_stencil ? VK_TRUE : VK_FALSE,
|
|
||||||
.front = copy_stencil ? REPLACE_STENCIL_OP : VkStencilOpState{},
|
|
||||||
.back = copy_stencil ? REPLACE_STENCIL_OP : VkStencilOpState{},
|
|
||||||
.minDepthBounds = 0.0f,
|
|
||||||
.maxDepthBounds = 0.0f,
|
|
||||||
};
|
|
||||||
const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci =
|
|
||||||
GetPipelineInputAssemblyStateCreateInfo(device);
|
|
||||||
pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({
|
|
||||||
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.flags = 0,
|
|
||||||
.stageCount = static_cast<u32>(stages.size()),
|
|
||||||
.pStages = stages.data(),
|
|
||||||
.pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
|
||||||
.pInputAssemblyState = &input_assembly_ci,
|
|
||||||
.pTessellationState = nullptr,
|
|
||||||
.pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO,
|
|
||||||
.pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
|
|
||||||
.pMultisampleState = &multisample_ci,
|
|
||||||
.pDepthStencilState = &depth_stencil_ci,
|
|
||||||
.pColorBlendState = &PIPELINE_COLOR_BLEND_STATE_EMPTY_CREATE_INFO,
|
|
||||||
.pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO,
|
|
||||||
.layout = copy_stencil ? *msaa_copy_depth_stencil_pipeline_layout
|
|
||||||
: *msaa_copy_pipeline_layout,
|
|
||||||
.renderPass = key.renderpass,
|
|
||||||
.subpass = 0,
|
|
||||||
.basePipelineHandle = VK_NULL_HANDLE,
|
|
||||||
.basePipelineIndex = 0,
|
|
||||||
}));
|
|
||||||
return *pipelines.back();
|
|
||||||
}
|
|
||||||
|
|
||||||
void BlitImageHelper::ConvertDepthToColorPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass) {
|
void BlitImageHelper::ConvertDepthToColorPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass) {
|
||||||
ConvertPipeline(pipeline, renderpass, false);
|
ConvertPipeline(pipeline, renderpass, false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,19 +45,12 @@ struct BlitDepthStencilPipelineKey {
|
|||||||
u32 stencil_ref;
|
u32 stencil_ref;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class MSAACopyFormatClass : u32 {
|
|
||||||
Float,
|
|
||||||
SignedInteger,
|
|
||||||
UnsignedInteger,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MSAACopyPipelineKey {
|
struct MSAACopyPipelineKey {
|
||||||
constexpr auto operator<=>(const MSAACopyPipelineKey&) const noexcept = default;
|
constexpr auto operator<=>(const MSAACopyPipelineKey&) const noexcept = default;
|
||||||
|
|
||||||
VkRenderPass renderpass;
|
VkRenderPass renderpass;
|
||||||
VkSampleCountFlagBits samples;
|
VkSampleCountFlagBits samples;
|
||||||
bool msaa_to_non_msaa;
|
bool msaa_to_non_msaa;
|
||||||
MSAACopyFormatClass format_class;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BlitMSAAPipelineKey {
|
struct BlitMSAAPipelineKey {
|
||||||
@@ -85,12 +78,6 @@ public:
|
|||||||
void BlitColorMSAA(const Framebuffer* dst_framebuffer, const ImageView& src_image_view,
|
void BlitColorMSAA(const Framebuffer* dst_framebuffer, const ImageView& src_image_view,
|
||||||
const Region2D& dst_region, const Region2D& src_region);
|
const Region2D& dst_region, const Region2D& src_region);
|
||||||
|
|
||||||
void BlitDepthStencilMSAA(const Framebuffer* dst_framebuffer, ImageView& src_image_view,
|
|
||||||
const Region2D& dst_region, const Region2D& src_region);
|
|
||||||
|
|
||||||
void BlitDepth(const Framebuffer* dst_framebuffer, ImageView& src_image_view,
|
|
||||||
const Region2D& dst_region, const Region2D& src_region);
|
|
||||||
|
|
||||||
void ResolveDepthStencil(const Framebuffer* dst_framebuffer, ImageView& src_image_view,
|
void ResolveDepthStencil(const Framebuffer* dst_framebuffer, ImageView& src_image_view,
|
||||||
const Region2D& dst_region, const Region2D& src_region);
|
const Region2D& dst_region, const Region2D& src_region);
|
||||||
|
|
||||||
@@ -129,39 +116,7 @@ public:
|
|||||||
VideoCore::Surface::PixelFormat src_format, u32 num_samples,
|
VideoCore::Surface::PixelFormat src_format, u32 num_samples,
|
||||||
std::span<const VideoCommon::ImageCopy> copies, bool msaa_to_non_msaa);
|
std::span<const VideoCommon::ImageCopy> copies, bool msaa_to_non_msaa);
|
||||||
|
|
||||||
void CopyMSAADepth(RenderPassCache& render_pass_cache, VkImage dst_image,
|
|
||||||
VideoCore::Surface::PixelFormat dst_format, VkImage src_image,
|
|
||||||
VideoCore::Surface::PixelFormat src_format, u32 num_samples,
|
|
||||||
std::span<const VideoCommon::ImageCopy> copies, bool copy_stencil,
|
|
||||||
bool msaa_to_non_msaa);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct MSAACopyAspectInfo {
|
|
||||||
VkImageAspectFlags src_view_aspect;
|
|
||||||
VkImageAspectFlags attachment_aspect;
|
|
||||||
VkImageAspectFlags barrier_aspect;
|
|
||||||
VkAccessFlags pre_src_access;
|
|
||||||
VkAccessFlags pre_src_dst_access;
|
|
||||||
VkAccessFlags pre_dst_dst_access;
|
|
||||||
VkPipelineStageFlags pre_src_stages;
|
|
||||||
VkPipelineStageFlags pre_dst_stages;
|
|
||||||
VkAccessFlags post_src_access;
|
|
||||||
VkAccessFlags post_dst_access;
|
|
||||||
VkPipelineStageFlags post_src_stages;
|
|
||||||
VkPipelineStageFlags post_dst_stages;
|
|
||||||
};
|
|
||||||
|
|
||||||
void BlitImpl(const Framebuffer* dst_framebuffer, const ImageView& src_image_view,
|
|
||||||
const Region2D& dst_region, const Region2D& src_region, VkPipeline pipeline,
|
|
||||||
VkSampler sampler, VkImageView src_view, VkImageView src_stencil_view,
|
|
||||||
bool blit_stencil);
|
|
||||||
|
|
||||||
void CopyMSAAImpl(VkRenderPass renderpass, VkPipeline pipeline, VkPipelineLayout layout,
|
|
||||||
VkImage dst_image, VkFormat dst_vk_format, VkImage src_image,
|
|
||||||
VkFormat src_vk_format, s32 scale_x, s32 scale_y,
|
|
||||||
std::span<const VideoCommon::ImageCopy> copies,
|
|
||||||
const MSAACopyAspectInfo& aspect_info, bool copy_stencil);
|
|
||||||
|
|
||||||
void Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
|
void Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
|
||||||
const ImageView& src_image_view);
|
const ImageView& src_image_view);
|
||||||
|
|
||||||
@@ -176,13 +131,7 @@ private:
|
|||||||
[[nodiscard]] VkPipeline FindOrEmplaceClearStencilPipeline(
|
[[nodiscard]] VkPipeline FindOrEmplaceClearStencilPipeline(
|
||||||
const BlitDepthStencilPipelineKey& key);
|
const BlitDepthStencilPipelineKey& key);
|
||||||
[[nodiscard]] VkPipeline FindOrEmplaceMSAACopyPipeline(const MSAACopyPipelineKey& key);
|
[[nodiscard]] VkPipeline FindOrEmplaceMSAACopyPipeline(const MSAACopyPipelineKey& key);
|
||||||
|
|
||||||
[[nodiscard]] VkPipeline FindOrEmplaceMSAACopyDepthPipeline(const MSAACopyPipelineKey& key,
|
|
||||||
bool copy_stencil);
|
|
||||||
[[nodiscard]] VkPipeline FindOrEmplaceBlitColorMSAAPipeline(const BlitMSAAPipelineKey& key);
|
[[nodiscard]] VkPipeline FindOrEmplaceBlitColorMSAAPipeline(const BlitMSAAPipelineKey& key);
|
||||||
[[nodiscard]] VkPipeline FindOrEmplaceBlitDepthStencilMSAAPipeline(
|
|
||||||
const BlitMSAAPipelineKey& key, bool blit_stencil);
|
|
||||||
[[nodiscard]] VkPipeline FindOrEmplaceBlitDepthPipeline(VkRenderPass renderpass);
|
|
||||||
[[nodiscard]] VkPipeline FindOrEmplaceResolveDepthStencilPipeline(VkRenderPass renderpass,
|
[[nodiscard]] VkPipeline FindOrEmplaceResolveDepthStencilPipeline(VkRenderPass renderpass,
|
||||||
bool resolve_stencil);
|
bool resolve_stencil);
|
||||||
|
|
||||||
@@ -213,12 +162,10 @@ private:
|
|||||||
vk::PipelineLayout two_textures_pipeline_layout;
|
vk::PipelineLayout two_textures_pipeline_layout;
|
||||||
vk::PipelineLayout clear_color_pipeline_layout;
|
vk::PipelineLayout clear_color_pipeline_layout;
|
||||||
vk::PipelineLayout msaa_copy_pipeline_layout;
|
vk::PipelineLayout msaa_copy_pipeline_layout;
|
||||||
vk::PipelineLayout msaa_copy_depth_stencil_pipeline_layout;
|
|
||||||
vk::ShaderModule full_screen_vert;
|
vk::ShaderModule full_screen_vert;
|
||||||
vk::ShaderModule blit_color_to_color_frag;
|
vk::ShaderModule blit_color_to_color_frag;
|
||||||
vk::ShaderModule blit_color_msaa_frag;
|
vk::ShaderModule blit_color_msaa_frag;
|
||||||
vk::ShaderModule blit_depth_stencil_frag;
|
vk::ShaderModule blit_depth_stencil_frag;
|
||||||
vk::ShaderModule blit_depth_frag;
|
|
||||||
vk::ShaderModule blit_depth_msaa_frag;
|
vk::ShaderModule blit_depth_msaa_frag;
|
||||||
vk::ShaderModule blit_depth_stencil_msaa_frag;
|
vk::ShaderModule blit_depth_stencil_msaa_frag;
|
||||||
vk::ShaderModule clear_color_vert;
|
vk::ShaderModule clear_color_vert;
|
||||||
@@ -232,15 +179,7 @@ private:
|
|||||||
vk::ShaderModule convert_d24s8_to_abgr8_frag;
|
vk::ShaderModule convert_d24s8_to_abgr8_frag;
|
||||||
vk::ShaderModule convert_s8d24_to_abgr8_frag;
|
vk::ShaderModule convert_s8d24_to_abgr8_frag;
|
||||||
vk::ShaderModule convert_msaa_to_non_msaa_frag;
|
vk::ShaderModule convert_msaa_to_non_msaa_frag;
|
||||||
vk::ShaderModule convert_msaa_to_non_msaa_sint_frag;
|
|
||||||
vk::ShaderModule convert_msaa_to_non_msaa_uint_frag;
|
|
||||||
vk::ShaderModule convert_msaa_to_non_msaa_depth_frag;
|
|
||||||
vk::ShaderModule convert_msaa_to_non_msaa_depth_stencil_frag;
|
|
||||||
vk::ShaderModule convert_non_msaa_to_msaa_frag;
|
vk::ShaderModule convert_non_msaa_to_msaa_frag;
|
||||||
vk::ShaderModule convert_non_msaa_to_msaa_sint_frag;
|
|
||||||
vk::ShaderModule convert_non_msaa_to_msaa_uint_frag;
|
|
||||||
vk::ShaderModule convert_non_msaa_to_msaa_depth_frag;
|
|
||||||
vk::ShaderModule convert_non_msaa_to_msaa_depth_stencil_frag;
|
|
||||||
vk::Sampler linear_sampler;
|
vk::Sampler linear_sampler;
|
||||||
vk::Sampler nearest_sampler;
|
vk::Sampler nearest_sampler;
|
||||||
|
|
||||||
@@ -254,18 +193,8 @@ private:
|
|||||||
std::vector<vk::Pipeline> clear_stencil_pipelines;
|
std::vector<vk::Pipeline> clear_stencil_pipelines;
|
||||||
std::vector<MSAACopyPipelineKey> msaa_copy_keys;
|
std::vector<MSAACopyPipelineKey> msaa_copy_keys;
|
||||||
std::vector<vk::Pipeline> msaa_copy_pipelines;
|
std::vector<vk::Pipeline> msaa_copy_pipelines;
|
||||||
std::vector<MSAACopyPipelineKey> msaa_copy_depth_keys;
|
|
||||||
std::vector<vk::Pipeline> msaa_copy_depth_pipelines;
|
|
||||||
std::vector<MSAACopyPipelineKey> msaa_copy_depth_stencil_keys;
|
|
||||||
std::vector<vk::Pipeline> msaa_copy_depth_stencil_pipelines;
|
|
||||||
std::vector<BlitMSAAPipelineKey> blit_msaa_color_keys;
|
std::vector<BlitMSAAPipelineKey> blit_msaa_color_keys;
|
||||||
std::vector<vk::Pipeline> blit_msaa_color_pipelines;
|
std::vector<vk::Pipeline> blit_msaa_color_pipelines;
|
||||||
std::vector<VkRenderPass> blit_depth_keys;
|
|
||||||
std::vector<vk::Pipeline> blit_depth_pipelines;
|
|
||||||
std::vector<BlitMSAAPipelineKey> blit_msaa_depth_keys;
|
|
||||||
std::vector<vk::Pipeline> blit_msaa_depth_pipelines;
|
|
||||||
std::vector<BlitMSAAPipelineKey> blit_msaa_depth_stencil_keys;
|
|
||||||
std::vector<vk::Pipeline> blit_msaa_depth_stencil_pipelines;
|
|
||||||
std::vector<VkRenderPass> resolve_depth_keys;
|
std::vector<VkRenderPass> resolve_depth_keys;
|
||||||
std::vector<vk::Pipeline> resolve_depth_pipelines;
|
std::vector<vk::Pipeline> resolve_depth_pipelines;
|
||||||
std::vector<VkRenderPass> resolve_depth_stencil_keys;
|
std::vector<VkRenderPass> resolve_depth_stencil_keys;
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/div_ceil.h"
|
#include "common/div_ceil.h"
|
||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
@@ -19,7 +17,7 @@
|
|||||||
|
|
||||||
namespace Vulkan {
|
namespace Vulkan {
|
||||||
|
|
||||||
using PushConstants = std::array<u32, 4 + 2 + 2 + 1>;
|
using PushConstants = std::array<u32, 4 + 2 + 1>;
|
||||||
|
|
||||||
SGSR::SGSR(const Device& device, MemoryAllocator& memory_allocator, size_t image_count, VkExtent2D extent, bool edge_dir)
|
SGSR::SGSR(const Device& device, MemoryAllocator& memory_allocator, size_t image_count, VkExtent2D extent, bool edge_dir)
|
||||||
: m_memory_allocator{memory_allocator}
|
: m_memory_allocator{memory_allocator}
|
||||||
@@ -102,28 +100,26 @@ VkImageView SGSR::Draw(const Device& device, Scheduler& scheduler, size_t image_
|
|||||||
|
|
||||||
const f32 input_image_width = f32(input_image_extent.width);
|
const f32 input_image_width = f32(input_image_extent.width);
|
||||||
const f32 input_image_height = f32(input_image_extent.height);
|
const f32 input_image_height = f32(input_image_extent.height);
|
||||||
const f32 crop_width = (crop_rect.right - crop_rect.left) * input_image_width;
|
const f32 viewport_width = (crop_rect.right - crop_rect.left) * input_image_width;
|
||||||
const f32 crop_height = (crop_rect.bottom - crop_rect.top) * input_image_height;
|
const f32 viewport_height = (crop_rect.bottom - crop_rect.top) * input_image_height;
|
||||||
static constexpr f32 EDGE_SHARPNESS_MAX = 2.0f;
|
// expected [0, 2]
|
||||||
const f32 edge_sharpness =
|
const f32 sharpening = f32(Settings::values.fsr_sharpening_slider.GetValue()) / 100.0f;
|
||||||
EDGE_SHARPNESS_MAX - f32(Settings::values.fsr_sharpening_slider.GetValue()) / 200.0f;
|
|
||||||
|
|
||||||
|
// p = (tex * viewport) / input = [0,n] (normalized texcoords)
|
||||||
|
// p * input = [0,1024], [0,768]
|
||||||
// layout( push_constant ) uniform constants {
|
// layout( push_constant ) uniform constants {
|
||||||
// highp vec4 ViewportInfo[1];
|
// highp vec4 ViewportInfo[1];
|
||||||
// highp vec2 ResizeFactor;
|
// highp vec2 ResizeFactor;
|
||||||
// highp vec2 CropOffset;
|
|
||||||
// highp float EdgeSharpness;
|
// highp float EdgeSharpness;
|
||||||
// };
|
// };
|
||||||
PushConstants viewport_con{};
|
PushConstants viewport_con{};
|
||||||
viewport_con[0] = std::bit_cast<u32>(1.f / input_image_width);
|
viewport_con[0] = std::bit_cast<u32>(std::abs(1.f / viewport_width));
|
||||||
viewport_con[1] = std::bit_cast<u32>(1.f / input_image_height);
|
viewport_con[1] = std::bit_cast<u32>(std::abs(1.f / viewport_height));
|
||||||
viewport_con[2] = std::bit_cast<u32>(input_image_width);
|
viewport_con[2] = std::bit_cast<u32>(std::abs(viewport_width));
|
||||||
viewport_con[3] = std::bit_cast<u32>(input_image_height);
|
viewport_con[3] = std::bit_cast<u32>(std::abs(viewport_height));
|
||||||
viewport_con[4] = std::bit_cast<u32>(crop_width / input_image_width);
|
viewport_con[4] = std::bit_cast<u32>(viewport_width / input_image_width);
|
||||||
viewport_con[5] = std::bit_cast<u32>(crop_height / input_image_height);
|
viewport_con[5] = std::bit_cast<u32>(viewport_height / input_image_height);
|
||||||
viewport_con[6] = std::bit_cast<u32>((std::min)(crop_rect.left, crop_rect.right));
|
viewport_con[6] = std::bit_cast<u32>(sharpening);
|
||||||
viewport_con[7] = std::bit_cast<u32>((std::min)(crop_rect.top, crop_rect.bottom));
|
|
||||||
viewport_con[8] = std::bit_cast<u32>(edge_sharpness);
|
|
||||||
|
|
||||||
UploadImages(device, scheduler);
|
UploadImages(device, scheduler);
|
||||||
UpdateDescriptorSets(device, source_image_view, image_index);
|
UpdateDescriptorSets(device, source_image_view, image_index);
|
||||||
|
|||||||
@@ -372,7 +372,7 @@ PipelineCache::PipelineCache(Tegra::MaxwellDeviceMemoryManager& device_memory_,
|
|||||||
subgroup_stage_bit(VK_SHADER_STAGE_COMPUTE_BIT, Shader::Stage::Compute)};
|
subgroup_stage_bit(VK_SHADER_STAGE_COMPUTE_BIT, Shader::Stage::Compute)};
|
||||||
profile = Shader::Profile{
|
profile = Shader::Profile{
|
||||||
.supported_spirv = device.SupportedSpirvVersion(),
|
.supported_spirv = device.SupportedSpirvVersion(),
|
||||||
.unified_descriptor_binding = false,
|
.unified_descriptor_binding = true,
|
||||||
.support_descriptor_aliasing = device.IsDescriptorAliasingSupported(),
|
.support_descriptor_aliasing = device.IsDescriptorAliasingSupported(),
|
||||||
.support_int8 = device.IsInt8Supported(),
|
.support_int8 = device.IsInt8Supported(),
|
||||||
.support_uniform_and_storage_buffer_8bit =
|
.support_uniform_and_storage_buffer_8bit =
|
||||||
@@ -383,18 +383,18 @@ PipelineCache::PipelineCache(Tegra::MaxwellDeviceMemoryManager& device_memory_,
|
|||||||
device.IsUniformAndStorageBuffer16BitAccessSupported(),
|
device.IsUniformAndStorageBuffer16BitAccessSupported(),
|
||||||
.support_storage_buffer_16bit = device.IsStorageBuffer16BitAccessSupported(),
|
.support_storage_buffer_16bit = device.IsStorageBuffer16BitAccessSupported(),
|
||||||
.support_int64 = device.IsShaderInt64Supported(),
|
.support_int64 = device.IsShaderInt64Supported(),
|
||||||
.support_vertex_instance_id = true,
|
.support_vertex_instance_id = false,
|
||||||
.support_float_controls = device.IsKhrShaderFloatControlsSupported(),
|
.support_float_controls = device.IsKhrShaderFloatControlsSupported(),
|
||||||
.support_separate_denorm_behavior =
|
.support_separate_denorm_behavior =
|
||||||
float_control.denormBehaviorIndependence == VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL,
|
float_control.denormBehaviorIndependence == VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL,
|
||||||
.support_separate_rounding_mode =
|
.support_separate_rounding_mode =
|
||||||
float_control.roundingModeIndependence == VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL,
|
float_control.roundingModeIndependence == VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL,
|
||||||
.support_fp16_denorm_preserve = false,
|
.support_fp16_denorm_preserve = float_control.shaderDenormPreserveFloat16 != VK_FALSE,
|
||||||
.support_fp32_denorm_preserve = float_control.shaderDenormPreserveFloat32 != VK_FALSE,
|
.support_fp32_denorm_preserve = float_control.shaderDenormPreserveFloat32 != VK_FALSE,
|
||||||
.support_fp16_denorm_flush = false,
|
.support_fp16_denorm_flush = float_control.shaderDenormFlushToZeroFloat16 != VK_FALSE,
|
||||||
.support_fp32_denorm_flush = float_control.shaderDenormFlushToZeroFloat32 != VK_FALSE,
|
.support_fp32_denorm_flush = float_control.shaderDenormFlushToZeroFloat32 != VK_FALSE,
|
||||||
.support_fp16_signed_zero_nan_preserve =
|
.support_fp16_signed_zero_nan_preserve =
|
||||||
false,
|
float_control.shaderSignedZeroInfNanPreserveFloat16 != VK_FALSE,
|
||||||
.support_fp32_signed_zero_nan_preserve =
|
.support_fp32_signed_zero_nan_preserve =
|
||||||
float_control.shaderSignedZeroInfNanPreserveFloat32 != VK_FALSE,
|
float_control.shaderSignedZeroInfNanPreserveFloat32 != VK_FALSE,
|
||||||
.support_fp64_signed_zero_nan_preserve =
|
.support_fp64_signed_zero_nan_preserve =
|
||||||
@@ -431,20 +431,20 @@ PipelineCache::PipelineCache(Tegra::MaxwellDeviceMemoryManager& device_memory_,
|
|||||||
|
|
||||||
.warp_size_potentially_larger_than_guest = device.IsWarpSizePotentiallyBiggerThanGuest(),
|
.warp_size_potentially_larger_than_guest = device.IsWarpSizePotentiallyBiggerThanGuest(),
|
||||||
|
|
||||||
.lower_left_origin_mode = true,
|
.lower_left_origin_mode = false,
|
||||||
.need_declared_frag_colors = true,
|
.need_declared_frag_colors = false,
|
||||||
.need_gather_subpixel_offset = driver_id == VK_DRIVER_ID_AMD_PROPRIETARY ||
|
.need_gather_subpixel_offset = driver_id == VK_DRIVER_ID_AMD_PROPRIETARY ||
|
||||||
driver_id == VK_DRIVER_ID_AMD_OPEN_SOURCE ||
|
driver_id == VK_DRIVER_ID_AMD_OPEN_SOURCE ||
|
||||||
driver_id == VK_DRIVER_ID_MESA_RADV ||
|
driver_id == VK_DRIVER_ID_MESA_RADV ||
|
||||||
driver_id == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS ||
|
driver_id == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS ||
|
||||||
driver_id == VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA,
|
driver_id == VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA,
|
||||||
|
|
||||||
.has_broken_spirv_clamp = true,
|
.has_broken_spirv_clamp = driver_id == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS,
|
||||||
.has_broken_spirv_position_input = driver_id == false,
|
.has_broken_spirv_position_input = driver_id == false,
|
||||||
.has_broken_unsigned_image_offsets = true,
|
.has_broken_unsigned_image_offsets = false,
|
||||||
.has_broken_signed_operations = true,
|
.has_broken_signed_operations = false,
|
||||||
.has_broken_fp16_float_controls = false,
|
.has_broken_fp16_float_controls = driver_id == VK_DRIVER_ID_NVIDIA_PROPRIETARY,
|
||||||
.ignore_nan_fp_comparisons = true,
|
.ignore_nan_fp_comparisons = false,
|
||||||
.has_broken_spirv_subgroup_mask_vector_extract_dynamic = false,
|
.has_broken_spirv_subgroup_mask_vector_extract_dynamic = false,
|
||||||
.has_broken_robust =
|
.has_broken_robust =
|
||||||
device.IsNvidia() && device.GetNvidiaArch() <= NvidiaArchitecture::Arch_Pascal,
|
device.IsNvidia() && device.GetNvidiaArch() <= NvidiaArchitecture::Arch_Pascal,
|
||||||
@@ -464,13 +464,13 @@ PipelineCache::PipelineCache(Tegra::MaxwellDeviceMemoryManager& device_memory_,
|
|||||||
.max_descriptor_set_sampled_images = device.GetMaxDescriptorSetSampledImages(),
|
.max_descriptor_set_sampled_images = device.GetMaxDescriptorSetSampledImages(),
|
||||||
.max_descriptor_set_storage_images = device.GetMaxDescriptorSetStorageImages(),
|
.max_descriptor_set_storage_images = device.GetMaxDescriptorSetStorageImages(),
|
||||||
.max_descriptor_set_input_attachements = device.GetMaxDescriptorSetInputAttachments(),
|
.max_descriptor_set_input_attachements = device.GetMaxDescriptorSetInputAttachments(),
|
||||||
.support_float64 = true,
|
.support_float64 = device.IsFloat64Supported(),
|
||||||
.support_float16 = false,
|
.support_float16 = device.IsFloat16Supported(),
|
||||||
.support_int64 = device.IsShaderInt64Supported(),
|
.support_int64 = device.IsShaderInt64Supported(),
|
||||||
.needs_demote_reorder = driver_id == VK_DRIVER_ID_AMD_PROPRIETARY ||
|
.needs_demote_reorder = driver_id == VK_DRIVER_ID_AMD_PROPRIETARY ||
|
||||||
driver_id == VK_DRIVER_ID_AMD_OPEN_SOURCE ||
|
driver_id == VK_DRIVER_ID_AMD_OPEN_SOURCE ||
|
||||||
driver_id == VK_DRIVER_ID_SAMSUNG_PROPRIETARY,
|
driver_id == VK_DRIVER_ID_SAMSUNG_PROPRIETARY,
|
||||||
.support_snorm_render_buffer = false,
|
.support_snorm_render_buffer = true,
|
||||||
.support_viewport_index_layer = device.IsExtShaderViewportIndexLayerSupported(),
|
.support_viewport_index_layer = device.IsExtShaderViewportIndexLayerSupported(),
|
||||||
.support_geometry_shader_passthrough = device.IsNvGeometryShaderPassthroughSupported(),
|
.support_geometry_shader_passthrough = device.IsNvGeometryShaderPassthroughSupported(),
|
||||||
.support_conditional_barrier = device.SupportsConditionalBarriers(),
|
.support_conditional_barrier = device.SupportsConditionalBarriers(),
|
||||||
|
|||||||
@@ -424,12 +424,24 @@ void RasterizerVulkan::Clear(u32 layer_count) {
|
|||||||
const bool ds_deferrable =
|
const bool ds_deferrable =
|
||||||
!ds_used || ((!framebuffer->HasAspectDepthBit() || use_depth) &&
|
!ds_used || ((!framebuffer->HasAspectDepthBit() || use_depth) &&
|
||||||
(!framebuffer->HasAspectStencilBit() || use_stencil) && !stencil_partial);
|
(!framebuffer->HasAspectStencilBit() || use_stencil) && !stencil_partial);
|
||||||
|
const bool can_defer_clear = ENABLE_DEFERRED_CLEAR && !regs.clear_control.use_scissor &&
|
||||||
|
regs.clear_surface.layer == 0 &&
|
||||||
|
!scheduler.IsRenderPassActive() &&
|
||||||
|
(!use_color || color_full_channels) && ds_deferrable;
|
||||||
|
if (!can_defer_clear) {
|
||||||
|
scheduler.RequestRenderpass(framebuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
query_cache.NotifySegment(true);
|
||||||
|
query_cache.CounterEnable(VideoCommon::QueryType::ZPassPixelCount64, maxwell3d->regs.zpass_pixel_count_enable);
|
||||||
u32 up_scale = 1;
|
u32 up_scale = 1;
|
||||||
u32 down_shift = 0;
|
u32 down_shift = 0;
|
||||||
if (texture_cache.IsRescaling()) {
|
if (texture_cache.IsRescaling()) {
|
||||||
up_scale = Settings::values.resolution_info.up_scale;
|
up_scale = Settings::values.resolution_info.up_scale;
|
||||||
down_shift = Settings::values.resolution_info.down_shift;
|
down_shift = Settings::values.resolution_info.down_shift;
|
||||||
}
|
}
|
||||||
|
UpdateViewportsState(regs);
|
||||||
|
|
||||||
VkRect2D default_scissor{};
|
VkRect2D default_scissor{};
|
||||||
default_scissor.offset.x = 0;
|
default_scissor.offset.x = 0;
|
||||||
default_scissor.offset.y = 0;
|
default_scissor.offset.y = 0;
|
||||||
@@ -485,22 +497,6 @@ void RasterizerVulkan::Clear(u32 layer_count) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool clear_covers_render_area =
|
|
||||||
clear_rect.rect.offset.x == 0 && clear_rect.rect.offset.y == 0 &&
|
|
||||||
clear_rect.rect.extent.width >= render_area.width &&
|
|
||||||
clear_rect.rect.extent.height >= render_area.height;
|
|
||||||
const bool can_defer_clear = ENABLE_DEFERRED_CLEAR && (!regs.clear_control.use_scissor || clear_covers_render_area) &&
|
|
||||||
regs.clear_surface.layer == 0 &&
|
|
||||||
!scheduler.IsRenderPassActive() &&
|
|
||||||
(!use_color || color_full_channels) && ds_deferrable;
|
|
||||||
if (!can_defer_clear) {
|
|
||||||
scheduler.RequestRenderpass(framebuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
query_cache.NotifySegment(true);
|
|
||||||
query_cache.CounterEnable(VideoCommon::QueryType::ZPassPixelCount64, maxwell3d->regs.zpass_pixel_count_enable);
|
|
||||||
UpdateViewportsState(regs);
|
|
||||||
|
|
||||||
const u32 color_attachment = regs.clear_surface.RT;
|
const u32 color_attachment = regs.clear_surface.RT;
|
||||||
if (use_color && framebuffer->HasAspectColorBit(color_attachment)) {
|
if (use_color && framebuffer->HasAspectColorBit(color_attachment)) {
|
||||||
const auto format = VideoCore::Surface::PixelFormatFromRenderTargetFormat(regs.rt[color_attachment].format);
|
const auto format = VideoCore::Surface::PixelFormatFromRenderTargetFormat(regs.rt[color_attachment].format);
|
||||||
|
|||||||
@@ -65,72 +65,8 @@ using VideoCore::Surface::SurfaceType;
|
|||||||
.finalLayout = VK_IMAGE_LAYOUT_GENERAL,
|
.finalLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ResolveAspects {
|
|
||||||
bool depth;
|
|
||||||
bool stencil;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ResolveModes {
|
|
||||||
VkResolveModeFlagBits depth;
|
|
||||||
VkResolveModeFlagBits stencil;
|
|
||||||
};
|
|
||||||
|
|
||||||
constexpr ResolveAspects GetResolveAspects(PixelFormat format) {
|
|
||||||
const SurfaceType surface_type = GetSurfaceType(format);
|
|
||||||
return ResolveAspects{
|
|
||||||
.depth = surface_type == SurfaceType::Depth ||
|
|
||||||
surface_type == SurfaceType::DepthStencil,
|
|
||||||
.stencil = surface_type == SurfaceType::Stencil ||
|
|
||||||
surface_type == SurfaceType::DepthStencil,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
ResolveModes PickResolveModes(const Device& device, PixelFormat format) {
|
|
||||||
constexpr VkResolveModeFlagBits mode = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
|
|
||||||
|
|
||||||
const ResolveAspects aspects = GetResolveAspects(format);
|
|
||||||
const bool depth_mode_supported = (device.GetDepthResolveModes() & mode) != 0;
|
|
||||||
const bool stencil_mode_supported = (device.GetStencilResolveModes() & mode) != 0;
|
|
||||||
|
|
||||||
ResolveModes modes{
|
|
||||||
.depth = VK_RESOLVE_MODE_NONE,
|
|
||||||
.stencil = VK_RESOLVE_MODE_NONE,
|
|
||||||
};
|
|
||||||
if (aspects.depth && depth_mode_supported) {
|
|
||||||
modes.depth = mode;
|
|
||||||
}
|
|
||||||
if (aspects.stencil && stencil_mode_supported) {
|
|
||||||
modes.stencil = mode;
|
|
||||||
}
|
|
||||||
if (modes.depth == modes.stencil || device.SupportsIndependentResolveNone()) {
|
|
||||||
return modes;
|
|
||||||
}
|
|
||||||
if (modes.depth != VK_RESOLVE_MODE_NONE && stencil_mode_supported) {
|
|
||||||
modes.stencil = mode;
|
|
||||||
} else if (modes.stencil != VK_RESOLVE_MODE_NONE && depth_mode_supported) {
|
|
||||||
modes.depth = mode;
|
|
||||||
}
|
|
||||||
return modes;
|
|
||||||
}
|
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
bool SupportsDepthStencilResolve(const Device& device, PixelFormat depth_format) {
|
|
||||||
if (depth_format == PixelFormat::Invalid || !device.IsKhrDepthStencilResolveSupported()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const ResolveAspects aspects = GetResolveAspects(depth_format);
|
|
||||||
if (!aspects.depth && !aspects.stencil) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const ResolveModes modes = PickResolveModes(device, depth_format);
|
|
||||||
if ((aspects.depth && modes.depth == VK_RESOLVE_MODE_NONE) ||
|
|
||||||
(aspects.stencil && modes.stencil == VK_RESOLVE_MODE_NONE)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return modes.depth == modes.stencil || device.SupportsIndependentResolveNone();
|
|
||||||
}
|
|
||||||
|
|
||||||
RenderPassCache::RenderPassCache(const Device& device_) : device{&device_} {}
|
RenderPassCache::RenderPassCache(const Device& device_) : device{&device_} {}
|
||||||
|
|
||||||
VkRenderPass RenderPassCache::Get(const RenderPassKey& key) {
|
VkRenderPass RenderPassCache::Get(const RenderPassKey& key) {
|
||||||
@@ -139,9 +75,7 @@ VkRenderPass RenderPassCache::Get(const RenderPassKey& key) {
|
|||||||
if (!is_new) {
|
if (!is_new) {
|
||||||
return *pair->second;
|
return *pair->second;
|
||||||
}
|
}
|
||||||
static constexpr size_t MAX_ATTACHMENTS =
|
boost::container::static_vector<VkAttachmentDescription, 9> descriptions;
|
||||||
2 * std::tuple_size_v<decltype(RenderPassKey::color_formats)> + 2;
|
|
||||||
boost::container::static_vector<VkAttachmentDescription, MAX_ATTACHMENTS> descriptions;
|
|
||||||
std::array<VkAttachmentReference, 8> references{};
|
std::array<VkAttachmentReference, 8> references{};
|
||||||
u32 num_attachments{};
|
u32 num_attachments{};
|
||||||
u32 num_colors{};
|
u32 num_colors{};
|
||||||
@@ -175,11 +109,8 @@ VkRenderPass RenderPassCache::Get(const RenderPassKey& key) {
|
|||||||
const VkAttachmentLoadOp depth_load_op = key.depth_stencil_clear
|
const VkAttachmentLoadOp depth_load_op = key.depth_stencil_clear
|
||||||
? VK_ATTACHMENT_LOAD_OP_CLEAR
|
? VK_ATTACHMENT_LOAD_OP_CLEAR
|
||||||
: VK_ATTACHMENT_LOAD_OP_LOAD;
|
: VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||||
const VkAttachmentStoreOp depth_store_op = key.depth_stencil_discard
|
|
||||||
? VK_ATTACHMENT_STORE_OP_DONT_CARE
|
|
||||||
: VK_ATTACHMENT_STORE_OP_STORE;
|
|
||||||
descriptions.push_back(AttachmentDescription(*device, key.depth_format, key.samples,
|
descriptions.push_back(AttachmentDescription(*device, key.depth_format, key.samples,
|
||||||
depth_load_op, depth_store_op));
|
depth_load_op, VK_ATTACHMENT_STORE_OP_STORE));
|
||||||
}
|
}
|
||||||
std::array<VkAttachmentReference, 8> resolve_references{};
|
std::array<VkAttachmentReference, 8> resolve_references{};
|
||||||
const bool do_resolve_color =
|
const bool do_resolve_color =
|
||||||
@@ -202,21 +133,6 @@ VkRenderPass RenderPassCache::Get(const RenderPassKey& key) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const bool do_resolve_depth_stencil = key.resolve_depth_stencil && has_depth &&
|
|
||||||
key.samples != VK_SAMPLE_COUNT_1_BIT &&
|
|
||||||
SupportsDepthStencilResolve(*device, key.depth_format);
|
|
||||||
VkAttachmentReference depth_resolve_reference{};
|
|
||||||
if (do_resolve_depth_stencil) {
|
|
||||||
depth_resolve_reference = VkAttachmentReference{
|
|
||||||
.attachment = static_cast<u32>(descriptions.size()),
|
|
||||||
.layout = VK_IMAGE_LAYOUT_GENERAL,
|
|
||||||
};
|
|
||||||
VkAttachmentDescription resolve_desc =
|
|
||||||
AttachmentDescription(*device, key.depth_format, VK_SAMPLE_COUNT_1_BIT,
|
|
||||||
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_STORE);
|
|
||||||
resolve_desc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
|
||||||
descriptions.push_back(resolve_desc);
|
|
||||||
}
|
|
||||||
const VkSubpassDescription subpass{
|
const VkSubpassDescription subpass{
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
|
.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||||
@@ -241,92 +157,6 @@ VkRenderPass RenderPassCache::Get(const RenderPassKey& key) {
|
|||||||
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT,
|
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT,
|
||||||
.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT
|
.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT
|
||||||
};
|
};
|
||||||
|
|
||||||
if (device->IsKhrCreateRenderPass2Supported()) {
|
|
||||||
boost::container::static_vector<VkAttachmentDescription2, MAX_ATTACHMENTS> descriptions2;
|
|
||||||
for (const VkAttachmentDescription& description : descriptions) {
|
|
||||||
descriptions2.push_back(VkAttachmentDescription2{
|
|
||||||
.sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.flags = description.flags,
|
|
||||||
.format = description.format,
|
|
||||||
.samples = description.samples,
|
|
||||||
.loadOp = description.loadOp,
|
|
||||||
.storeOp = description.storeOp,
|
|
||||||
.stencilLoadOp = description.stencilLoadOp,
|
|
||||||
.stencilStoreOp = description.stencilStoreOp,
|
|
||||||
.initialLayout = description.initialLayout,
|
|
||||||
.finalLayout = description.finalLayout,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const auto promote = [](const VkAttachmentReference& reference) {
|
|
||||||
return VkAttachmentReference2{
|
|
||||||
.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.attachment = reference.attachment,
|
|
||||||
.layout = reference.layout,
|
|
||||||
.aspectMask = 0,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
std::array<VkAttachmentReference2, 8> references2{};
|
|
||||||
std::array<VkAttachmentReference2, 8> resolve_references2{};
|
|
||||||
for (size_t index = 0; index < references.size(); ++index) {
|
|
||||||
references2[index] = promote(references[index]);
|
|
||||||
resolve_references2[index] = promote(resolve_references[index]);
|
|
||||||
}
|
|
||||||
const VkAttachmentReference2 depth_reference2 = promote(depth_reference);
|
|
||||||
const VkAttachmentReference2 depth_resolve_reference2 = promote(depth_resolve_reference);
|
|
||||||
const ResolveModes resolve_modes = PickResolveModes(*device, key.depth_format);
|
|
||||||
const VkSubpassDescriptionDepthStencilResolve depth_stencil_resolve{
|
|
||||||
.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.depthResolveMode = resolve_modes.depth,
|
|
||||||
.stencilResolveMode = resolve_modes.stencil,
|
|
||||||
.pDepthStencilResolveAttachment = &depth_resolve_reference2,
|
|
||||||
};
|
|
||||||
const VkSubpassDescription2 subpass2{
|
|
||||||
.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2,
|
|
||||||
.pNext = do_resolve_depth_stencil ? &depth_stencil_resolve : nullptr,
|
|
||||||
.flags = 0,
|
|
||||||
.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
|
|
||||||
.viewMask = 0,
|
|
||||||
.inputAttachmentCount = 0,
|
|
||||||
.pInputAttachments = nullptr,
|
|
||||||
.colorAttachmentCount = num_attachments,
|
|
||||||
.pColorAttachments = references2.data(),
|
|
||||||
.pResolveAttachments = do_resolve_color ? resolve_references2.data() : nullptr,
|
|
||||||
.pDepthStencilAttachment = has_depth ? &depth_reference2 : nullptr,
|
|
||||||
.preserveAttachmentCount = 0,
|
|
||||||
.pPreserveAttachments = nullptr,
|
|
||||||
};
|
|
||||||
const VkSubpassDependency2 dependency2{
|
|
||||||
.sType = VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.srcSubpass = dependency.srcSubpass,
|
|
||||||
.dstSubpass = dependency.dstSubpass,
|
|
||||||
.srcStageMask = dependency.srcStageMask,
|
|
||||||
.dstStageMask = dependency.dstStageMask,
|
|
||||||
.srcAccessMask = dependency.srcAccessMask,
|
|
||||||
.dstAccessMask = dependency.dstAccessMask,
|
|
||||||
.dependencyFlags = dependency.dependencyFlags,
|
|
||||||
.viewOffset = 0,
|
|
||||||
};
|
|
||||||
pair->second = device->GetLogical().CreateRenderPass2({
|
|
||||||
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.flags = 0,
|
|
||||||
.attachmentCount = static_cast<u32>(descriptions2.size()),
|
|
||||||
.pAttachments = descriptions2.empty() ? nullptr : descriptions2.data(),
|
|
||||||
.subpassCount = 1,
|
|
||||||
.pSubpasses = &subpass2,
|
|
||||||
.dependencyCount = 1,
|
|
||||||
.pDependencies = &dependency2,
|
|
||||||
.correlatedViewMaskCount = 0,
|
|
||||||
.pCorrelatedViewMasks = nullptr,
|
|
||||||
});
|
|
||||||
return *pair->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
pair->second = device->GetLogical().CreateRenderPass({
|
pair->second = device->GetLogical().CreateRenderPass({
|
||||||
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <ankerl/unordered_dense.h>
|
#include <ankerl/unordered_dense.h>
|
||||||
|
|
||||||
#include "common/container_hash.h"
|
|
||||||
#include "video_core/surface.h"
|
#include "video_core/surface.h"
|
||||||
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
||||||
|
|
||||||
@@ -22,11 +21,9 @@ struct RenderPassKey {
|
|||||||
VideoCore::Surface::PixelFormat depth_format;
|
VideoCore::Surface::PixelFormat depth_format;
|
||||||
VkSampleCountFlagBits samples;
|
VkSampleCountFlagBits samples;
|
||||||
bool resolve_color;
|
bool resolve_color;
|
||||||
bool resolve_depth_stencil;
|
|
||||||
u32 color_clear_mask;
|
u32 color_clear_mask;
|
||||||
bool depth_stencil_clear;
|
bool depth_stencil_clear;
|
||||||
u32 color_discard_mask;
|
u32 color_discard_mask;
|
||||||
bool depth_stencil_discard;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Vulkan
|
} // namespace Vulkan
|
||||||
@@ -34,28 +31,17 @@ struct RenderPassKey {
|
|||||||
namespace std {
|
namespace std {
|
||||||
template <>
|
template <>
|
||||||
struct hash<Vulkan::RenderPassKey> {
|
struct hash<Vulkan::RenderPassKey> {
|
||||||
static_assert(std::tuple_size_v<decltype(Vulkan::RenderPassKey::color_formats)> <= 8);
|
|
||||||
static_assert(static_cast<u32>(VideoCore::Surface::PixelFormat::Invalid) <= 0xFF);
|
|
||||||
static_assert(static_cast<u32>(VideoCore::Surface::PixelFormat::Max) <= 0xFF);
|
|
||||||
static_assert(VK_SAMPLE_COUNT_64_BIT <= 0xFF);
|
|
||||||
|
|
||||||
[[nodiscard]] size_t operator()(const Vulkan::RenderPassKey& key) const noexcept {
|
[[nodiscard]] size_t operator()(const Vulkan::RenderPassKey& key) const noexcept {
|
||||||
u64 formats = 0;
|
size_t value = static_cast<size_t>(key.depth_format) << 48;
|
||||||
for (size_t index = 0; index < key.color_formats.size(); ++index) {
|
value ^= static_cast<size_t>(key.samples) << 52;
|
||||||
formats |= static_cast<u64>(key.color_formats[index]) << (index * 8);
|
value ^= static_cast<size_t>(key.resolve_color) << 63;
|
||||||
|
value ^= static_cast<size_t>(key.color_clear_mask) << 54;
|
||||||
|
value ^= static_cast<size_t>(key.depth_stencil_clear) << 62;
|
||||||
|
value ^= static_cast<size_t>(key.color_discard_mask) << 24;
|
||||||
|
for (size_t i = 0; i < key.color_formats.size(); ++i) {
|
||||||
|
value ^= static_cast<size_t>(key.color_formats[i]) << (i * 6);
|
||||||
}
|
}
|
||||||
const u64 state = static_cast<u64>(key.depth_format) |
|
return value;
|
||||||
(static_cast<u64>(key.samples) << 8) |
|
|
||||||
(static_cast<u64>(key.color_clear_mask) << 16) |
|
|
||||||
(static_cast<u64>(key.color_discard_mask) << 24) |
|
|
||||||
(static_cast<u64>(key.resolve_color) << 32) |
|
|
||||||
(static_cast<u64>(key.depth_stencil_clear) << 33) |
|
|
||||||
(static_cast<u64>(key.resolve_depth_stencil) << 34) |
|
|
||||||
(static_cast<u64>(key.depth_stencil_discard) << 35);
|
|
||||||
size_t seed = 0;
|
|
||||||
Common::HashCombine(seed, formats);
|
|
||||||
Common::HashCombine(seed, state);
|
|
||||||
return seed;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // namespace std
|
} // namespace std
|
||||||
@@ -64,9 +50,6 @@ namespace Vulkan {
|
|||||||
|
|
||||||
class Device;
|
class Device;
|
||||||
|
|
||||||
[[nodiscard]] bool SupportsDepthStencilResolve(const Device& device,
|
|
||||||
VideoCore::Surface::PixelFormat depth_format);
|
|
||||||
|
|
||||||
class RenderPassCache {
|
class RenderPassCache {
|
||||||
public:
|
public:
|
||||||
explicit RenderPassCache(const Device& device_);
|
explicit RenderPassCache(const Device& device_);
|
||||||
|
|||||||
@@ -132,7 +132,6 @@ void Scheduler::BeginRenderPassImpl(const Framebuffer* framebuffer, VkRenderPass
|
|||||||
num_renderpass_images = framebuffer->NumImages();
|
num_renderpass_images = framebuffer->NumImages();
|
||||||
renderpass_images = framebuffer->Images();
|
renderpass_images = framebuffer->Images();
|
||||||
renderpass_image_ranges = framebuffer->ImageRanges();
|
renderpass_image_ranges = framebuffer->ImageRanges();
|
||||||
framebuffer->MarkResolveShadowsUpToDate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scheduler::RealizeDeferredClear() {
|
void Scheduler::RealizeDeferredClear() {
|
||||||
@@ -156,10 +155,8 @@ void Scheduler::RealizeDeferredClear() {
|
|||||||
}
|
}
|
||||||
const u32 color_discard_mask =
|
const u32 color_discard_mask =
|
||||||
dc.framebuffer->DiscardsMsaaColor() ? dc.color_clear_mask : 0u;
|
dc.framebuffer->DiscardsMsaaColor() ? dc.color_clear_mask : 0u;
|
||||||
const bool depth_stencil_discard =
|
|
||||||
dc.depth_stencil && dc.framebuffer->DiscardsMsaaDepthStencil();
|
|
||||||
const VkRenderPass renderpass = dc.framebuffer->RenderPassVariant(
|
const VkRenderPass renderpass = dc.framebuffer->RenderPassVariant(
|
||||||
dc.color_clear_mask, dc.depth_stencil, color_discard_mask, depth_stencil_discard);
|
dc.color_clear_mask, dc.depth_stencil, color_discard_mask);
|
||||||
EndRenderPass();
|
EndRenderPass();
|
||||||
BeginRenderPassImpl(dc.framebuffer, renderpass, clear_values.data(), count);
|
BeginRenderPassImpl(dc.framebuffer, renderpass, clear_values.data(), count);
|
||||||
}
|
}
|
||||||
@@ -193,14 +190,6 @@ bool Scheduler::DeferDepthStencilClear(const Framebuffer* framebuffer, const VkC
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scheduler::FlushDeferredClear() {
|
|
||||||
if (deferred_clear.framebuffer == nullptr) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
RealizeDeferredClear();
|
|
||||||
EndRenderPass();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scheduler::RequestRenderpass(const Framebuffer* framebuffer) {
|
void Scheduler::RequestRenderpass(const Framebuffer* framebuffer) {
|
||||||
if (deferred_clear.framebuffer == framebuffer) {
|
if (deferred_clear.framebuffer == framebuffer) {
|
||||||
RealizeDeferredClear();
|
RealizeDeferredClear();
|
||||||
|
|||||||
@@ -65,9 +65,6 @@ public:
|
|||||||
/// Defers a full depth/stencil clear so it becomes the next render pass.
|
/// Defers a full depth/stencil clear so it becomes the next render pass.
|
||||||
bool DeferDepthStencilClear(const Framebuffer* framebuffer, const VkClearValue& value);
|
bool DeferDepthStencilClear(const Framebuffer* framebuffer, const VkClearValue& value);
|
||||||
|
|
||||||
/// Realizes any pending deferred clear before its framebuffer can be moved or freed.
|
|
||||||
void FlushDeferredClear();
|
|
||||||
|
|
||||||
/// Requests the current execution context to be able to execute operations only allowed outside
|
/// Requests the current execution context to be able to execute operations only allowed outside
|
||||||
/// of a renderpass.
|
/// of a renderpass.
|
||||||
void RequestOutsideRenderPassOperationContext();
|
void RequestOutsideRenderPassOperationContext();
|
||||||
|
|||||||
@@ -33,10 +33,10 @@ constexpr VkDeviceSize MAX_ALIGNMENT = 256;
|
|||||||
// Windows ones however, can intake bigger buffers and generally do not OOM.
|
// Windows ones however, can intake bigger buffers and generally do not OOM.
|
||||||
// - GTX 960 on Windows will not OOM with 256mib
|
// - GTX 960 on Windows will not OOM with 256mib
|
||||||
// - GT 1030 on ^NIX will OOM with 256mib
|
// - GT 1030 on ^NIX will OOM with 256mib
|
||||||
#if defined(__FreeBSD__)
|
#if defined(_WIN32) || defined(__ANDROID__)
|
||||||
constexpr VkDeviceSize MAX_STREAM_BUFFER_SIZE = 128_MiB;
|
|
||||||
#else
|
|
||||||
constexpr VkDeviceSize MAX_STREAM_BUFFER_SIZE = 256_MiB;
|
constexpr VkDeviceSize MAX_STREAM_BUFFER_SIZE = 256_MiB;
|
||||||
|
#else
|
||||||
|
constexpr VkDeviceSize MAX_STREAM_BUFFER_SIZE = 128_MiB;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
size_t GetStreamBufferSize(const Device& device) {
|
size_t GetStreamBufferSize(const Device& device) {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -60,8 +60,6 @@ public:
|
|||||||
|
|
||||||
void TickFrame();
|
void TickFrame();
|
||||||
|
|
||||||
void FlushDeferredClear();
|
|
||||||
|
|
||||||
u64 GetDeviceLocalMemory() const;
|
u64 GetDeviceLocalMemory() const;
|
||||||
|
|
||||||
u64 GetDeviceMemoryUsage() const;
|
u64 GetDeviceMemoryUsage() const;
|
||||||
@@ -70,12 +68,6 @@ public:
|
|||||||
|
|
||||||
std::optional<size_t> GetSamplerHeapBudget() const;
|
std::optional<size_t> GetSamplerHeapBudget() const;
|
||||||
|
|
||||||
bool CanDownloadMsaa(const VideoCommon::ImageInfo& info) const;
|
|
||||||
|
|
||||||
[[nodiscard]] VkImage AcquireMsaaScratchImage(const VkImageCreateInfo& image_ci);
|
|
||||||
|
|
||||||
void ReleaseMsaaScratchImage(VkImage image);
|
|
||||||
|
|
||||||
void BlitImage(Framebuffer* dst_framebuffer, ImageView& dst, ImageView& src,
|
void BlitImage(Framebuffer* dst_framebuffer, ImageView& dst, ImageView& src,
|
||||||
const Region2D& dst_region, const Region2D& src_region,
|
const Region2D& dst_region, const Region2D& src_region,
|
||||||
Tegra::Engines::Fermi2D::Filter filter,
|
Tegra::Engines::Fermi2D::Filter filter,
|
||||||
@@ -125,20 +117,16 @@ public:
|
|||||||
VkFormat format = VK_FORMAT_UNDEFINED;
|
VkFormat format = VK_FORMAT_UNDEFINED;
|
||||||
VkExtent2D extent{};
|
VkExtent2D extent{};
|
||||||
u32 layers = 0;
|
u32 layers = 0;
|
||||||
VkImageAspectFlags aspect_mask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
||||||
bool up_to_date = false;
|
bool up_to_date = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
[[nodiscard]] VkImageView GetOrCreateResolveShadow(VkImage msaa_image, VkFormat format,
|
[[nodiscard]] VkImageView GetOrCreateResolveShadow(VkImage msaa_image, VkFormat format,
|
||||||
VkExtent2D extent, u32 layers,
|
VkExtent2D extent, u32 layers);
|
||||||
VkImageAspectFlags aspect_mask);
|
|
||||||
|
|
||||||
[[nodiscard]] const ResolveShadow* GetValidResolveShadow(VkImage msaa_image) const;
|
[[nodiscard]] const ResolveShadow* GetValidResolveShadow(VkImage msaa_image) const;
|
||||||
|
|
||||||
void InvalidateResolveShadow(VkImage msaa_image);
|
void InvalidateResolveShadow(VkImage msaa_image);
|
||||||
|
|
||||||
void MarkResolveShadowUpToDate(VkImage msaa_image);
|
|
||||||
|
|
||||||
void EraseResolveShadow(VkImage msaa_image);
|
void EraseResolveShadow(VkImage msaa_image);
|
||||||
|
|
||||||
std::span<const VkFormat> ViewFormats(PixelFormat format) {
|
std::span<const VkFormat> ViewFormats(PixelFormat format) {
|
||||||
@@ -166,30 +154,8 @@ public:
|
|||||||
|
|
||||||
static constexpr size_t indexing_slots = 8 * sizeof(size_t);
|
static constexpr size_t indexing_slots = 8 * sizeof(size_t);
|
||||||
std::array<vk::Buffer, indexing_slots> buffers{};
|
std::array<vk::Buffer, indexing_slots> buffers{};
|
||||||
struct MsaaScratchKey {
|
std::vector<std::pair<u64, vk::Image>> pending_msaa_images;
|
||||||
VkFormat format;
|
|
||||||
VkImageType type;
|
|
||||||
u32 width;
|
|
||||||
u32 height;
|
|
||||||
u32 depth;
|
|
||||||
u32 levels;
|
|
||||||
u32 layers;
|
|
||||||
VkImageUsageFlags usage;
|
|
||||||
VkImageCreateFlags flags;
|
|
||||||
|
|
||||||
bool operator==(const MsaaScratchKey&) const noexcept = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MsaaScratchImage {
|
|
||||||
MsaaScratchKey key;
|
|
||||||
vk::Image image;
|
|
||||||
u64 tick;
|
|
||||||
u32 unused_frames;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<MsaaScratchImage> msaa_scratch_images;
|
|
||||||
ankerl::unordered_dense::map<VkImage, ResolveShadow> resolve_shadows;
|
ankerl::unordered_dense::map<VkImage, ResolveShadow> resolve_shadows;
|
||||||
std::vector<std::pair<u64, ResolveShadow>> pending_resolve_shadows;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Framebuffer {
|
class Framebuffer {
|
||||||
@@ -225,8 +191,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] VkRenderPass RenderPassVariant(u32 color_clear_mask, bool depth_stencil_clear,
|
[[nodiscard]] VkRenderPass RenderPassVariant(u32 color_clear_mask, bool depth_stencil_clear,
|
||||||
u32 color_discard_mask,
|
u32 color_discard_mask) const;
|
||||||
bool depth_stencil_discard) const;
|
|
||||||
|
|
||||||
[[nodiscard]] VkExtent2D RenderArea() const noexcept {
|
[[nodiscard]] VkExtent2D RenderArea() const noexcept {
|
||||||
return render_area;
|
return render_area;
|
||||||
@@ -268,21 +233,19 @@ public:
|
|||||||
return is_rescaled;
|
return is_rescaled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool HasResolveColor() const noexcept {
|
||||||
|
return !resolve_images.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] VkImage ResolveColorImage(size_t index) const noexcept {
|
||||||
|
return index < resolve_images.size() ? *resolve_images[index] : VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] bool DiscardsMsaaColor() const noexcept {
|
[[nodiscard]] bool DiscardsMsaaColor() const noexcept {
|
||||||
return discard_msaa_color;
|
return discard_msaa_color;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] bool DiscardsMsaaDepthStencil() const noexcept {
|
|
||||||
return discard_msaa_depth_stencil;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Records that a render pass has begun, so its resolve attachments will hold valid contents
|
|
||||||
/// once it ends.
|
|
||||||
void MarkResolveShadowsUpToDate() const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr size_t NUM_MEMOIZED_RENDER_PASS_VARIANTS = 8;
|
|
||||||
|
|
||||||
vk::Framebuffer framebuffer;
|
vk::Framebuffer framebuffer;
|
||||||
VkRenderPass renderpass{};
|
VkRenderPass renderpass{};
|
||||||
VkExtent2D render_area{};
|
VkExtent2D render_area{};
|
||||||
@@ -295,16 +258,11 @@ private:
|
|||||||
bool has_depth{};
|
bool has_depth{};
|
||||||
bool has_stencil{};
|
bool has_stencil{};
|
||||||
bool is_rescaled{};
|
bool is_rescaled{};
|
||||||
std::array<VkImage, 9> resolve_shadow_images{};
|
std::vector<vk::Image> resolve_images;
|
||||||
u32 num_resolve_shadows = 0;
|
std::vector<vk::ImageView> resolve_image_views;
|
||||||
TextureCacheRuntime* runtime_ptr{nullptr};
|
|
||||||
RenderPassKey render_pass_key{};
|
RenderPassKey render_pass_key{};
|
||||||
RenderPassCache* render_pass_cache{nullptr};
|
RenderPassCache* render_pass_cache{nullptr};
|
||||||
bool discard_msaa_color{};
|
bool discard_msaa_color{};
|
||||||
bool discard_msaa_depth_stencil{};
|
|
||||||
mutable std::array<u32, NUM_MEMOIZED_RENDER_PASS_VARIANTS> variant_keys{};
|
|
||||||
mutable std::array<VkRenderPass, NUM_MEMOIZED_RENDER_PASS_VARIANTS> variant_render_passes{};
|
|
||||||
mutable u32 num_memoized_variants{};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Image : public VideoCommon::ImageBase {
|
class Image : public VideoCommon::ImageBase {
|
||||||
@@ -528,7 +486,6 @@ struct TextureCacheParams {
|
|||||||
static constexpr bool HAS_EMULATED_COPIES = false;
|
static constexpr bool HAS_EMULATED_COPIES = false;
|
||||||
static constexpr bool HAS_DEVICE_MEMORY_INFO = true;
|
static constexpr bool HAS_DEVICE_MEMORY_INFO = true;
|
||||||
static constexpr bool IMPLEMENTS_ASYNC_DOWNLOADS = true;
|
static constexpr bool IMPLEMENTS_ASYNC_DOWNLOADS = true;
|
||||||
static constexpr bool HAS_MSAA_DOWNLOADS = true;
|
|
||||||
|
|
||||||
using Runtime = Vulkan::TextureCacheRuntime;
|
using Runtime = Vulkan::TextureCacheRuntime;
|
||||||
using Image = Vulkan::Image;
|
using Image = Vulkan::Image;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||||
@@ -121,7 +121,7 @@ void ImageBase::InsertView(const ImageViewInfo& view_info, ImageViewId image_vie
|
|||||||
image_view_ids.push_back(image_view_id);
|
image_view_ids.push_back(image_view_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ImageBase::IsSafeGpuCopy() const noexcept {
|
bool ImageBase::IsSafeDownload() const noexcept {
|
||||||
// Skip images that were not modified from the GPU
|
// Skip images that were not modified from the GPU
|
||||||
if (False(flags & ImageFlagBits::GpuModified)) {
|
if (False(flags & ImageFlagBits::GpuModified)) {
|
||||||
return false;
|
return false;
|
||||||
@@ -131,6 +131,10 @@ bool ImageBase::IsSafeGpuCopy() const noexcept {
|
|||||||
if (True(flags & ImageFlagBits::CpuModified)) {
|
if (True(flags & ImageFlagBits::CpuModified)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (info.num_samples > 1) {
|
||||||
|
LOG_WARNING(HW_GPU, "MSAA image downloads are not implemented");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
@@ -67,7 +64,7 @@ struct ImageBase {
|
|||||||
|
|
||||||
void InsertView(const ImageViewInfo& view_info, ImageViewId image_view_id);
|
void InsertView(const ImageViewInfo& view_info, ImageViewId image_view_id);
|
||||||
|
|
||||||
[[nodiscard]] bool IsSafeGpuCopy() const noexcept;
|
[[nodiscard]] bool IsSafeDownload() const noexcept;
|
||||||
|
|
||||||
[[nodiscard]] bool Overlaps(VAddr overlap_cpu_addr, size_t overlap_size) const noexcept {
|
[[nodiscard]] bool Overlaps(VAddr overlap_cpu_addr, size_t overlap_size) const noexcept {
|
||||||
const VAddr overlap_end = overlap_cpu_addr + overlap_size;
|
const VAddr overlap_end = overlap_cpu_addr + overlap_size;
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ void TextureCache<P>::RunGarbageCollector() {
|
|||||||
if (True(image.flags & ImageFlagBits::IsDecoding)) {
|
if (True(image.flags & ImageFlagBits::IsDecoding)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const bool must_download = IsDownloadable(image) && False(image.flags & ImageFlagBits::BadOverlap);
|
const bool must_download = image.IsSafeDownload() && False(image.flags & ImageFlagBits::BadOverlap);
|
||||||
if ((!aggressive_mode && True(image.flags & ImageFlagBits::CostlyLoad)) || (!high_priority_mode && must_download)) {
|
if ((!aggressive_mode && True(image.flags & ImageFlagBits::CostlyLoad)) || (!high_priority_mode && must_download)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -577,7 +577,6 @@ FramebufferId TextureCache<P>::GetFramebufferId(const RenderTargets& key) {
|
|||||||
return id ? &slot_image_views[id] : nullptr;
|
return id ? &slot_image_views[id] : nullptr;
|
||||||
});
|
});
|
||||||
ImageView* const depth_buffer = key.depth_buffer_id ? &slot_image_views[key.depth_buffer_id] : nullptr;
|
ImageView* const depth_buffer = key.depth_buffer_id ? &slot_image_views[key.depth_buffer_id] : nullptr;
|
||||||
runtime.FlushDeferredClear();
|
|
||||||
framebuffer_id = slot_framebuffers.insert(runtime, color_buffers, depth_buffer, key);
|
framebuffer_id = slot_framebuffers.insert(runtime, color_buffers, depth_buffer, key);
|
||||||
return framebuffer_id;
|
return framebuffer_id;
|
||||||
}
|
}
|
||||||
@@ -595,26 +594,11 @@ void TextureCache<P>::WriteMemory(DAddr cpu_addr, size_t size) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class P>
|
|
||||||
bool TextureCache<P>::IsDownloadable(const ImageBase& image) const noexcept {
|
|
||||||
if (!image.IsSafeGpuCopy()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (image.info.num_samples == 1) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if constexpr (P::HAS_MSAA_DOWNLOADS) {
|
|
||||||
return runtime.CanDownloadMsaa(image.info);
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
void TextureCache<P>::DownloadMemory(DAddr cpu_addr, size_t size) {
|
void TextureCache<P>::DownloadMemory(DAddr cpu_addr, size_t size) {
|
||||||
boost::container::small_vector<ImageId, 16> images;
|
boost::container::small_vector<ImageId, 16> images;
|
||||||
ForEachImageInRegion(cpu_addr, size, [this, &images](ImageId image_id, ImageBase& image) {
|
ForEachImageInRegion(cpu_addr, size, [&images](ImageId image_id, ImageBase& image) {
|
||||||
if (!IsDownloadable(image)) {
|
if (!image.IsSafeDownload()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
image.flags &= ~ImageFlagBits::GpuModified;
|
image.flags &= ~ImageFlagBits::GpuModified;
|
||||||
@@ -1492,12 +1476,12 @@ template <class P>
|
|||||||
bool TextureCache<P>::ScaleUp(Image& image) {
|
bool TextureCache<P>::ScaleUp(Image& image) {
|
||||||
const bool has_copy = image.HasScaled();
|
const bool has_copy = image.HasScaled();
|
||||||
const bool rescaled = image.ScaleUp();
|
const bool rescaled = image.ScaleUp();
|
||||||
if (!has_copy && image.HasScaled()) {
|
|
||||||
total_used_memory += GetScaledImageSizeBytes(image);
|
|
||||||
}
|
|
||||||
if (!rescaled) {
|
if (!rescaled) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (!has_copy) {
|
||||||
|
total_used_memory += GetScaledImageSizeBytes(image);
|
||||||
|
}
|
||||||
InvalidateScale(image);
|
InvalidateScale(image);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1707,10 +1691,7 @@ ImageId TextureCache<P>::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, DA
|
|||||||
for (const auto& copy_object : join_copies_to_do) {
|
for (const auto& copy_object : join_copies_to_do) {
|
||||||
Image& overlap = slot_images[copy_object.id];
|
Image& overlap = slot_images[copy_object.id];
|
||||||
if (copy_object.is_alias) {
|
if (copy_object.is_alias) {
|
||||||
if (!overlap.IsSafeGpuCopy()) {
|
if (!overlap.IsSafeDownload()) {
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (overlap.info.num_samples != new_image.info.num_samples) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const auto alias_pointer = join_alias_indices.find(copy_object.id);
|
const auto alias_pointer = join_alias_indices.find(copy_object.id);
|
||||||
@@ -2480,7 +2461,6 @@ void TextureCache<P>::RemoveImageViewReferences(std::span<const ImageViewId> rem
|
|||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
void TextureCache<P>::RemoveFramebuffers(std::span<const ImageViewId> removed_views) {
|
void TextureCache<P>::RemoveFramebuffers(std::span<const ImageViewId> removed_views) {
|
||||||
runtime.FlushDeferredClear();
|
|
||||||
auto it = framebuffers.begin();
|
auto it = framebuffers.begin();
|
||||||
while (it != framebuffers.end()) {
|
while (it != framebuffers.end()) {
|
||||||
if (it->first.Contains(removed_views)) {
|
if (it->first.Contains(removed_views)) {
|
||||||
|
|||||||
@@ -303,8 +303,6 @@ private:
|
|||||||
FramebufferId GetFramebufferId(const RenderTargets& key);
|
FramebufferId GetFramebufferId(const RenderTargets& key);
|
||||||
|
|
||||||
/// Refresh the contents (pixel data) of an image
|
/// Refresh the contents (pixel data) of an image
|
||||||
[[nodiscard]] bool IsDownloadable(const ImageBase& image) const noexcept;
|
|
||||||
|
|
||||||
void RefreshContents(Image& image, ImageId image_id);
|
void RefreshContents(Image& image, ImageId image_id);
|
||||||
|
|
||||||
/// Upload data from guest to an image
|
/// Upload data from guest to an image
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||||
@@ -80,16 +80,16 @@ float TSCEntry::MaxAnisotropy() const noexcept {
|
|||||||
case Settings::AnisotropyMode::X4:
|
case Settings::AnisotropyMode::X4:
|
||||||
case Settings::AnisotropyMode::X8:
|
case Settings::AnisotropyMode::X8:
|
||||||
case Settings::AnisotropyMode::X16:
|
case Settings::AnisotropyMode::X16:
|
||||||
added_anisotropic = s32(anisotropic_settings) - 1;
|
case Settings::AnisotropyMode::X32:
|
||||||
|
case Settings::AnisotropyMode::X64:
|
||||||
|
added_anisotropic = u32(anisotropic_settings) - 1U;
|
||||||
break;
|
break;
|
||||||
case Settings::AnisotropyMode::Automatic: {
|
case Settings::AnisotropyMode::Automatic:
|
||||||
const u32 resolution_scale = Settings::values.resolution_info.up_scale >>
|
added_anisotropic = Settings::values.resolution_info.up_scale >> Settings::values.resolution_info.down_shift;
|
||||||
Settings::values.resolution_info.down_shift;
|
added_anisotropic = (std::max)(added_anisotropic - 1U, 0U);
|
||||||
if (resolution_scale > 1U) {
|
|
||||||
added_anisotropic = static_cast<s32>(resolution_scale - 1U);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
case Settings::AnisotropyMode::None:
|
||||||
|
return 1.0f; //No use of anisotropy
|
||||||
}
|
}
|
||||||
return float(1U << (max_anisotropy + added_anisotropic));
|
return float(1U << (max_anisotropy + added_anisotropic));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -650,6 +650,13 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
|||||||
features.shader_float16_int8.shaderFloat16 = false;
|
features.shader_float16_int8.shaderFloat16 = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_intel_windows) {
|
||||||
|
LOG_WARNING(Render_Vulkan,
|
||||||
|
"Intel proprietary drivers do not support MSAA->MSAA image blits. "
|
||||||
|
"MSAA scaling will use 3D helpers. MSAA resolves work normally.");
|
||||||
|
cant_blit_msaa = true;
|
||||||
|
}
|
||||||
|
|
||||||
has_broken_compute =
|
has_broken_compute =
|
||||||
CheckBrokenCompute(properties.driver.driverID, properties.properties.driverVersion) &&
|
CheckBrokenCompute(properties.driver.driverID, properties.properties.driverVersion) &&
|
||||||
!Settings::values.enable_compute_pipelines.GetValue();
|
!Settings::values.enable_compute_pipelines.GetValue();
|
||||||
@@ -968,12 +975,6 @@ bool Device::GetSuitability(bool requires_swapchain) {
|
|||||||
FOR_EACH_VK_FEATURE_EXT(FEATURE_EXTENSION);
|
FOR_EACH_VK_FEATURE_EXT(FEATURE_EXTENSION);
|
||||||
FOR_EACH_VK_EXTENSION(EXTENSION);
|
FOR_EACH_VK_EXTENSION(EXTENSION);
|
||||||
|
|
||||||
extensions.depth_stencil_resolve =
|
|
||||||
extensions.depth_stencil_resolve &&
|
|
||||||
(instance_version >= VK_API_VERSION_1_2 || extensions.create_renderpass2);
|
|
||||||
RemoveExtensionIfUnsuitable(extensions.depth_stencil_resolve,
|
|
||||||
VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME);
|
|
||||||
|
|
||||||
if (supported_extensions.contains(VK_KHR_ROBUSTNESS_2_EXTENSION_NAME)) {
|
if (supported_extensions.contains(VK_KHR_ROBUSTNESS_2_EXTENSION_NAME)) {
|
||||||
loaded_extensions.erase(VK_EXT_ROBUSTNESS_2_EXTENSION_NAME);
|
loaded_extensions.erase(VK_EXT_ROBUSTNESS_2_EXTENSION_NAME);
|
||||||
loaded_extensions.insert(VK_KHR_ROBUSTNESS_2_EXTENSION_NAME);
|
loaded_extensions.insert(VK_KHR_ROBUSTNESS_2_EXTENSION_NAME);
|
||||||
@@ -1121,11 +1122,6 @@ bool Device::GetSuitability(bool requires_swapchain) {
|
|||||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR;
|
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR;
|
||||||
SetNext(next, properties.push_descriptor);
|
SetNext(next, properties.push_descriptor);
|
||||||
}
|
}
|
||||||
if (extensions.depth_stencil_resolve || instance_version >= VK_API_VERSION_1_2) {
|
|
||||||
properties.depth_stencil_resolve.sType =
|
|
||||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES;
|
|
||||||
SetNext(next, properties.depth_stencil_resolve);
|
|
||||||
}
|
|
||||||
if (extensions.descriptor_buffer) {
|
if (extensions.descriptor_buffer) {
|
||||||
properties.descriptor_buffer.sType =
|
properties.descriptor_buffer.sType =
|
||||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_PROPERTIES_EXT;
|
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_PROPERTIES_EXT;
|
||||||
|
|||||||
@@ -91,8 +91,6 @@ VK_DEFINE_HANDLE(VmaAllocator)
|
|||||||
EXTENSION(EXT, SHADER_VIEWPORT_INDEX_LAYER, shader_viewport_index_layer) \
|
EXTENSION(EXT, SHADER_VIEWPORT_INDEX_LAYER, shader_viewport_index_layer) \
|
||||||
EXTENSION(EXT, TOOLING_INFO, tooling_info) \
|
EXTENSION(EXT, TOOLING_INFO, tooling_info) \
|
||||||
EXTENSION(EXT, VERTEX_ATTRIBUTE_DIVISOR, vertex_attribute_divisor) \
|
EXTENSION(EXT, VERTEX_ATTRIBUTE_DIVISOR, vertex_attribute_divisor) \
|
||||||
EXTENSION(KHR, CREATE_RENDERPASS_2, create_renderpass2) \
|
|
||||||
EXTENSION(KHR, DEPTH_STENCIL_RESOLVE, depth_stencil_resolve) \
|
|
||||||
EXTENSION(KHR, DRAW_INDIRECT_COUNT, draw_indirect_count) \
|
EXTENSION(KHR, DRAW_INDIRECT_COUNT, draw_indirect_count) \
|
||||||
EXTENSION(KHR, DRIVER_PROPERTIES, driver_properties) \
|
EXTENSION(KHR, DRIVER_PROPERTIES, driver_properties) \
|
||||||
EXTENSION(KHR, PUSH_DESCRIPTOR, push_descriptor) \
|
EXTENSION(KHR, PUSH_DESCRIPTOR, push_descriptor) \
|
||||||
@@ -615,32 +613,6 @@ FN_MAX_LIMIT_LIST
|
|||||||
return extensions.shader_stencil_export;
|
return extensions.shader_stencil_export;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if the device supports VK_KHR_create_renderpass2.
|
|
||||||
bool IsKhrCreateRenderPass2Supported() const {
|
|
||||||
return extensions.create_renderpass2 || instance_version >= VK_API_VERSION_1_2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns true if the device supports VK_KHR_depth_stencil_resolve.
|
|
||||||
bool IsKhrDepthStencilResolveSupported() const {
|
|
||||||
return (extensions.depth_stencil_resolve || instance_version >= VK_API_VERSION_1_2) &&
|
|
||||||
IsKhrCreateRenderPass2Supported();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the supported resolve modes for the depth aspect.
|
|
||||||
VkResolveModeFlags GetDepthResolveModes() const {
|
|
||||||
return properties.depth_stencil_resolve.supportedDepthResolveModes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the supported resolve modes for the stencil aspect.
|
|
||||||
VkResolveModeFlags GetStencilResolveModes() const {
|
|
||||||
return properties.depth_stencil_resolve.supportedStencilResolveModes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns true if only one of the depth and stencil aspects may be resolved.
|
|
||||||
bool SupportsIndependentResolveNone() const {
|
|
||||||
return properties.depth_stencil_resolve.independentResolveNone == VK_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns true if depth/stencil operations can be performed efficiently.
|
/// Returns true if depth/stencil operations can be performed efficiently.
|
||||||
/// Either through shader export or hardware blits.
|
/// Either through shader export or hardware blits.
|
||||||
bool CanPerformDepthStencilOperations() const {
|
bool CanPerformDepthStencilOperations() const {
|
||||||
@@ -949,6 +921,10 @@ FN_MAX_LIMIT_LIST
|
|||||||
return supports_d24_depth;
|
return supports_d24_depth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CantBlitMSAA() const {
|
||||||
|
return cant_blit_msaa;
|
||||||
|
}
|
||||||
|
|
||||||
bool MustEmulateScaledFormats() const {
|
bool MustEmulateScaledFormats() const {
|
||||||
return must_emulate_scaled_formats;
|
return must_emulate_scaled_formats;
|
||||||
}
|
}
|
||||||
@@ -1172,7 +1148,6 @@ private:
|
|||||||
VkPhysicalDeviceSubgroupSizeControlProperties subgroup_size_control{};
|
VkPhysicalDeviceSubgroupSizeControlProperties subgroup_size_control{};
|
||||||
VkPhysicalDeviceTransformFeedbackPropertiesEXT transform_feedback{};
|
VkPhysicalDeviceTransformFeedbackPropertiesEXT transform_feedback{};
|
||||||
VkPhysicalDeviceMaintenance5PropertiesKHR maintenance5{};
|
VkPhysicalDeviceMaintenance5PropertiesKHR maintenance5{};
|
||||||
VkPhysicalDeviceDepthStencilResolveProperties depth_stencil_resolve{};
|
|
||||||
|
|
||||||
VkPhysicalDeviceProperties properties{};
|
VkPhysicalDeviceProperties properties{};
|
||||||
};
|
};
|
||||||
@@ -1200,6 +1175,7 @@ private:
|
|||||||
bool has_nsight_graphics{}; ///< Has Nsight Graphics attached
|
bool has_nsight_graphics{}; ///< Has Nsight Graphics attached
|
||||||
bool has_radeon_gpu_profiler{}; ///< Has Radeon GPU Profiler attached.
|
bool has_radeon_gpu_profiler{}; ///< Has Radeon GPU Profiler attached.
|
||||||
bool supports_d24_depth{}; ///< Supports D24 depth buffers.
|
bool supports_d24_depth{}; ///< Supports D24 depth buffers.
|
||||||
|
bool cant_blit_msaa{}; ///< Does not support MSAA<->MSAA blitting.
|
||||||
bool must_emulate_scaled_formats{}; ///< Requires scaled vertex format emulation
|
bool must_emulate_scaled_formats{}; ///< Requires scaled vertex format emulation
|
||||||
bool dynamic_state3_blending{}; ///< Has blending features of dynamic_state3.
|
bool dynamic_state3_blending{}; ///< Has blending features of dynamic_state3.
|
||||||
bool dynamic_state3_enables{}; ///< Has at least one enable feature of dynamic_state3.
|
bool dynamic_state3_enables{}; ///< Has at least one enable feature of dynamic_state3.
|
||||||
|
|||||||
@@ -184,7 +184,6 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept {
|
|||||||
X(vkCreatePipelineLayout);
|
X(vkCreatePipelineLayout);
|
||||||
X(vkCreateQueryPool);
|
X(vkCreateQueryPool);
|
||||||
X(vkCreateRenderPass);
|
X(vkCreateRenderPass);
|
||||||
X(vkCreateRenderPass2);
|
|
||||||
X(vkCreateSampler);
|
X(vkCreateSampler);
|
||||||
X(vkCreateSemaphore);
|
X(vkCreateSemaphore);
|
||||||
X(vkCreateShaderModule);
|
X(vkCreateShaderModule);
|
||||||
@@ -271,10 +270,6 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept {
|
|||||||
if (!dld.vkQueueSubmit2) {
|
if (!dld.vkQueueSubmit2) {
|
||||||
Proc(dld.vkQueueSubmit2, dld, "vkQueueSubmit2KHR", device);
|
Proc(dld.vkQueueSubmit2, dld, "vkQueueSubmit2KHR", device);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dld.vkCreateRenderPass2) {
|
|
||||||
Proc(dld.vkCreateRenderPass2, dld, "vkCreateRenderPass2KHR", device);
|
|
||||||
}
|
|
||||||
#undef X
|
#undef X
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -730,12 +725,6 @@ RenderPass Device::CreateRenderPass(const VkRenderPassCreateInfo& ci) const {
|
|||||||
return RenderPass(object, handle, *dld);
|
return RenderPass(object, handle, *dld);
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderPass Device::CreateRenderPass2(const VkRenderPassCreateInfo2& ci) const {
|
|
||||||
VkRenderPass object;
|
|
||||||
Check(dld->vkCreateRenderPass2(handle, &ci, nullptr, &object));
|
|
||||||
return RenderPass(object, handle, *dld);
|
|
||||||
}
|
|
||||||
|
|
||||||
DescriptorSetLayout Device::CreateDescriptorSetLayout(
|
DescriptorSetLayout Device::CreateDescriptorSetLayout(
|
||||||
const VkDescriptorSetLayoutCreateInfo& ci) const {
|
const VkDescriptorSetLayoutCreateInfo& ci) const {
|
||||||
VkDescriptorSetLayout object;
|
VkDescriptorSetLayout object;
|
||||||
|
|||||||
@@ -300,7 +300,6 @@ struct DeviceDispatch : InstanceDispatch {
|
|||||||
PFN_vkCreatePipelineLayout vkCreatePipelineLayout{};
|
PFN_vkCreatePipelineLayout vkCreatePipelineLayout{};
|
||||||
PFN_vkCreateQueryPool vkCreateQueryPool{};
|
PFN_vkCreateQueryPool vkCreateQueryPool{};
|
||||||
PFN_vkCreateRenderPass vkCreateRenderPass{};
|
PFN_vkCreateRenderPass vkCreateRenderPass{};
|
||||||
PFN_vkCreateRenderPass2 vkCreateRenderPass2{};
|
|
||||||
PFN_vkCreateSampler vkCreateSampler{};
|
PFN_vkCreateSampler vkCreateSampler{};
|
||||||
PFN_vkCreateSemaphore vkCreateSemaphore{};
|
PFN_vkCreateSemaphore vkCreateSemaphore{};
|
||||||
PFN_vkCreateShaderModule vkCreateShaderModule{};
|
PFN_vkCreateShaderModule vkCreateShaderModule{};
|
||||||
@@ -1046,8 +1045,6 @@ public:
|
|||||||
|
|
||||||
[[nodiscard]] RenderPass CreateRenderPass(const VkRenderPassCreateInfo& ci) const;
|
[[nodiscard]] RenderPass CreateRenderPass(const VkRenderPassCreateInfo& ci) const;
|
||||||
|
|
||||||
[[nodiscard]] RenderPass CreateRenderPass2(const VkRenderPassCreateInfo2& ci) const;
|
|
||||||
|
|
||||||
[[nodiscard]] DescriptorSetLayout CreateDescriptorSetLayout(
|
[[nodiscard]] DescriptorSetLayout CreateDescriptorSetLayout(
|
||||||
const VkDescriptorSetLayoutCreateInfo& ci) const;
|
const VkDescriptorSetLayoutCreateInfo& ci) const;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user