This commit is contained in:
Timotej Leginus 2023-06-11 20:20:17 +02:00
commit d5129d9347
14 changed files with 380 additions and 494 deletions

View file

@ -3,4 +3,4 @@
[codespell] [codespell]
skip = ./.git,./build,./dist,./Doxyfile,./externals,./LICENSES skip = ./.git,./build,./dist,./Doxyfile,./externals,./LICENSES
ignore-words-list = aci,allright,ba,deques,froms,hda,inout,lod,masia,nam,nax,nd,pullrequests,pullrequest,te,transfered,unstall,uscaled,zink ignore-words-list = aci,allright,ba,deques,froms,hda,inout,lod,masia,nam,nax,nd,optin,pullrequests,pullrequest,te,transfered,unstall,uscaled,zink

View file

@ -223,6 +223,8 @@ object NativeLibrary {
external fun getCompany(filename: String): String external fun getCompany(filename: String): String
external fun isHomebrew(filename: String): Boolean
external fun setAppDirectory(directory: String) external fun setAppDirectory(directory: String)
external fun initializeGpuDriver( external fun initializeGpuDriver(

View file

@ -6,15 +6,12 @@ package org.yuzu.yuzu_emu.activities
import android.app.Activity import android.app.Activity
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.res.Configuration
import android.graphics.Rect import android.graphics.Rect
import android.hardware.Sensor import android.hardware.Sensor
import android.hardware.SensorEvent import android.hardware.SensorEvent
import android.hardware.SensorEventListener import android.hardware.SensorEventListener
import android.hardware.SensorManager import android.hardware.SensorManager
import android.hardware.display.DisplayManager
import android.os.Bundle import android.os.Bundle
import android.view.Display
import android.view.InputDevice import android.view.InputDevice
import android.view.KeyEvent import android.view.KeyEvent
import android.view.MotionEvent import android.view.MotionEvent
@ -23,7 +20,6 @@ import android.view.View
import android.view.inputmethod.InputMethodManager import android.view.inputmethod.InputMethodManager
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.getSystemService
import androidx.core.view.WindowCompat import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowInsetsControllerCompat import androidx.core.view.WindowInsetsControllerCompat
@ -39,7 +35,6 @@ import org.yuzu.yuzu_emu.features.settings.model.SettingsViewModel
import org.yuzu.yuzu_emu.fragments.EmulationFragment import org.yuzu.yuzu_emu.fragments.EmulationFragment
import org.yuzu.yuzu_emu.model.Game import org.yuzu.yuzu_emu.model.Game
import org.yuzu.yuzu_emu.utils.ControllerMappingHelper import org.yuzu.yuzu_emu.utils.ControllerMappingHelper
import org.yuzu.yuzu_emu.utils.EmulationMenuSettings
import org.yuzu.yuzu_emu.utils.ForegroundService import org.yuzu.yuzu_emu.utils.ForegroundService
import org.yuzu.yuzu_emu.utils.InputHandler import org.yuzu.yuzu_emu.utils.InputHandler
import org.yuzu.yuzu_emu.utils.NfcReader import org.yuzu.yuzu_emu.utils.NfcReader
@ -148,11 +143,6 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
super.onResume() super.onResume()
nfcReader.startScanning() nfcReader.startScanning()
startMotionSensorListener() startMotionSensorListener()
NativeLibrary.notifyOrientationChange(
EmulationMenuSettings.landscapeScreenLayout,
getAdjustedRotation()
)
} }
override fun onPause() { override fun onPause() {
@ -258,24 +248,6 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
override fun onAccuracyChanged(sensor: Sensor, i: Int) {} override fun onAccuracyChanged(sensor: Sensor, i: Int) {}
private fun getAdjustedRotation():Int {
val rotation = getSystemService<DisplayManager>()!!.getDisplay(Display.DEFAULT_DISPLAY).rotation
val config: Configuration = resources.configuration
if ((config.screenLayout and Configuration.SCREENLAYOUT_LONG_YES) != 0 ||
(config.screenLayout and Configuration.SCREENLAYOUT_LONG_NO) == 0 ||
(config.screenLayout and Configuration.SCREENLAYOUT_SIZE_SMALL) != 0) {
return rotation
}
when (rotation) {
Surface.ROTATION_0 -> return Surface.ROTATION_90
Surface.ROTATION_90 -> return Surface.ROTATION_0
Surface.ROTATION_180 -> return Surface.ROTATION_270
Surface.ROTATION_270 -> return Surface.ROTATION_180
}
return rotation
}
private fun restoreState(savedInstanceState: Bundle) { private fun restoreState(savedInstanceState: Bundle) {
game = savedInstanceState.parcelable(EXTRA_SELECTED_GAME)!! game = savedInstanceState.parcelable(EXTRA_SELECTED_GAME)!!
} }

View file

@ -127,13 +127,7 @@ class SearchFragment : Fragment() {
} }
} }
R.id.chip_homebrew -> { R.id.chip_homebrew -> baseList.filter { it.isHomebrew }
baseList.filter {
Log.error("Guh - ${it.path}")
FileUtil.hasExtension(it.path, "nro")
|| FileUtil.hasExtension(it.path, "nso")
}
}
R.id.chip_retail -> baseList.filter { R.id.chip_retail -> baseList.filter {
FileUtil.hasExtension(it.path, "xci") FileUtil.hasExtension(it.path, "xci")

View file

@ -16,7 +16,8 @@ class Game(
val regions: String, val regions: String,
val path: String, val path: String,
val gameId: String, val gameId: String,
val company: String val company: String,
val isHomebrew: Boolean
) : Parcelable { ) : Parcelable {
val keyAddedToLibraryTime get() = "${gameId}_AddedToLibraryTime" val keyAddedToLibraryTime get() = "${gameId}_AddedToLibraryTime"
val keyLastPlayedTime get() = "${gameId}_LastPlayed" val keyLastPlayedTime get() = "${gameId}_LastPlayed"
@ -31,6 +32,7 @@ class Game(
&& path == other.path && path == other.path
&& gameId == other.gameId && gameId == other.gameId
&& company == other.company && company == other.company
&& isHomebrew == other.isHomebrew
} }
companion object { companion object {

View file

@ -13,6 +13,8 @@ import androidx.preference.PreferenceManager
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.MissingFieldException
import kotlinx.serialization.decodeFromString import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import org.yuzu.yuzu_emu.NativeLibrary import org.yuzu.yuzu_emu.NativeLibrary
@ -20,6 +22,7 @@ import org.yuzu.yuzu_emu.YuzuApplication
import org.yuzu.yuzu_emu.utils.GameHelper import org.yuzu.yuzu_emu.utils.GameHelper
import java.util.Locale import java.util.Locale
@OptIn(ExperimentalSerializationApi::class)
class GamesViewModel : ViewModel() { class GamesViewModel : ViewModel() {
private val _games = MutableLiveData<List<Game>>(emptyList()) private val _games = MutableLiveData<List<Game>>(emptyList())
val games: LiveData<List<Game>> get() = _games val games: LiveData<List<Game>> get() = _games
@ -49,7 +52,13 @@ class GamesViewModel : ViewModel() {
if (storedGames!!.isNotEmpty()) { if (storedGames!!.isNotEmpty()) {
val deserializedGames = mutableSetOf<Game>() val deserializedGames = mutableSetOf<Game>()
storedGames.forEach { storedGames.forEach {
val game: Game = Json.decodeFromString(it) val game: Game
try {
game = Json.decodeFromString(it)
} catch (e: MissingFieldException) {
return@forEach
}
val gameExists = val gameExists =
DocumentFile.fromSingleUri(YuzuApplication.appContext, Uri.parse(game.path)) DocumentFile.fromSingleUri(YuzuApplication.appContext, Uri.parse(game.path))
?.exists() ?.exists()

View file

@ -765,8 +765,9 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
// If we have API access, calculate the safe area to draw the overlay // If we have API access, calculate the safe area to draw the overlay
var cutoutLeft = 0 var cutoutLeft = 0
var cutoutBottom = 0 var cutoutBottom = 0
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
val insets = context.windowManager.currentWindowMetrics.windowInsets.displayCutout val insets = context.windowManager.currentWindowMetrics.windowInsets.displayCutout
if (insets != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { if (insets != null) {
if (insets.boundingRectTop.bottom != 0 && insets.boundingRectTop.bottom > maxY / 2) if (insets.boundingRectTop.bottom != 0 && insets.boundingRectTop.bottom > maxY / 2)
insets.boundingRectTop.bottom.toFloat() else maxY insets.boundingRectTop.bottom.toFloat() else maxY
if (insets.boundingRectRight.left != 0 && insets.boundingRectRight.left > maxX / 2) if (insets.boundingRectRight.left != 0 && insets.boundingRectRight.left > maxX / 2)
@ -778,6 +779,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
cutoutLeft = insets.boundingRectRight.right - insets.boundingRectRight.left cutoutLeft = insets.boundingRectRight.right - insets.boundingRectRight.left
cutoutBottom = insets.boundingRectTop.top - insets.boundingRectTop.bottom cutoutBottom = insets.boundingRectTop.top - insets.boundingRectTop.bottom
} }
}
// This makes sure that if we have an inset on one side of the screen, we mirror it on // This makes sure that if we have an inset on one side of the screen, we mirror it on
// the other side. Since removing space from one of the max values messes with the scale, // the other side. Since removing space from one of the max values messes with the scale,

View file

@ -6,7 +6,6 @@ package org.yuzu.yuzu_emu.utils
import android.content.SharedPreferences import android.content.SharedPreferences
import android.net.Uri import android.net.Uri
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import org.yuzu.yuzu_emu.NativeLibrary import org.yuzu.yuzu_emu.NativeLibrary
@ -83,7 +82,8 @@ object GameHelper {
NativeLibrary.getRegions(filePath), NativeLibrary.getRegions(filePath),
filePath, filePath,
gameId, gameId,
NativeLibrary.getCompany(filePath) NativeLibrary.getCompany(filePath),
NativeLibrary.isHomebrew(filePath)
) )
val addedTime = preferences.getLong(newGame.keyAddedToLibraryTime, 0L) val addedTime = preferences.getLong(newGame.keyAddedToLibraryTime, 0L)

View file

@ -13,8 +13,7 @@
#include <android/api-level.h> #include <android/api-level.h>
#include <android/native_window_jni.h> #include <android/native_window_jni.h>
#include <network/room_member.h> #include <core/loader/nro.h>
#include <network/network.h>
#include "common/detached_tasks.h" #include "common/detached_tasks.h"
#include "common/dynamic_library.h" #include "common/dynamic_library.h"
@ -95,14 +94,6 @@ public:
m_native_window = native_window; m_native_window = native_window;
} }
u32 ScreenRotation() const {
return m_screen_rotation;
}
void SetScreenRotation(u32 screen_rotation) {
m_screen_rotation = screen_rotation;
}
void InitializeGpuDriver(const std::string& hook_lib_dir, const std::string& custom_driver_dir, void InitializeGpuDriver(const std::string& hook_lib_dir, const std::string& custom_driver_dir,
const std::string& custom_driver_name, const std::string& custom_driver_name,
const std::string& file_redirect_dir) { const std::string& file_redirect_dir) {
@ -283,6 +274,10 @@ public:
return GetRomMetadata(path).icon; return GetRomMetadata(path).icon;
} }
bool GetIsHomebrew(const std::string& path) {
return GetRomMetadata(path).isHomebrew;
}
void ResetRomMetadata() { void ResetRomMetadata() {
m_rom_metadata_cache.clear(); m_rom_metadata_cache.clear();
} }
@ -346,33 +341,11 @@ public:
return m_software_keyboard; return m_software_keyboard;
} }
void DirectConnectToRoom(const std::string& nickname, const char* server_addr = "127.0.0.1",
u16 server_port = Network::DefaultRoomPort,
const std::string& password = "") {
auto room_network = m_system.GetRoomNetwork();
if (const auto member = room_network.GetRoomMember().lock()) {
// Prevent the user from trying to join a room while they are already joining.
if (member->GetState() == Network::RoomMember::State::Joining || member->IsConnected()) {
return;
} else {
member->Join(nickname, server_addr, server_port);
}
}
}
Network::RoomMember::State GetRoomMemberState() {
if (const auto member = m_system.GetRoomNetwork().GetRoomMember().lock()) {
return member->GetState();
} else {
return Network::RoomMember::State::Idle;
}
}
private: private:
struct RomMetadata { struct RomMetadata {
std::string title; std::string title;
std::vector<u8> icon; std::vector<u8> icon;
bool isHomebrew;
}; };
RomMetadata GetRomMetadata(const std::string& path) { RomMetadata GetRomMetadata(const std::string& path) {
@ -385,11 +358,17 @@ private:
RomMetadata CacheRomMetadata(const std::string& path) { RomMetadata CacheRomMetadata(const std::string& path) {
const auto file = Core::GetGameFileFromPath(m_vfs, path); const auto file = Core::GetGameFileFromPath(m_vfs, path);
const auto loader = Loader::GetLoader(EmulationSession::GetInstance().System(), file, 0, 0); auto loader = Loader::GetLoader(EmulationSession::GetInstance().System(), file, 0, 0);
RomMetadata entry; RomMetadata entry;
loader->ReadTitle(entry.title); loader->ReadTitle(entry.title);
loader->ReadIcon(entry.icon); loader->ReadIcon(entry.icon);
if (loader->GetFileType() == Loader::FileType::NRO) {
auto loader_nro = dynamic_cast<Loader::AppLoader_NRO*>(loader.get());
entry.isHomebrew = loader_nro->IsHomebrew();
} else {
entry.isHomebrew = false;
}
m_rom_metadata_cache[path] = entry; m_rom_metadata_cache[path] = entry;
@ -413,7 +392,6 @@ private:
// Window management // Window management
std::unique_ptr<EmuWindow_Android> m_window; std::unique_ptr<EmuWindow_Android> m_window;
ANativeWindow* m_native_window{}; ANativeWindow* m_native_window{};
u32 m_screen_rotation{};
// Core emulation // Core emulation
Core::System m_system; Core::System m_system;
@ -439,10 +417,6 @@ private:
} // Anonymous namespace } // Anonymous namespace
u32 GetAndroidScreenRotation() {
return EmulationSession::GetInstance().ScreenRotation();
}
static Core::SystemResultStatus RunEmulation(const std::string& filepath) { static Core::SystemResultStatus RunEmulation(const std::string& filepath) {
Common::Log::Initialize(); Common::Log::Initialize();
Common::Log::SetColorConsoleBackendEnabled(true); Common::Log::SetColorConsoleBackendEnabled(true);
@ -486,13 +460,6 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_surfaceDestroyed(JNIEnv* env,
EmulationSession::GetInstance().SurfaceChanged(); EmulationSession::GetInstance().SurfaceChanged();
} }
void Java_org_yuzu_yuzu_1emu_NativeLibrary_notifyOrientationChange(JNIEnv* env,
[[maybe_unused]] jclass clazz,
jint layout_option,
jint rotation) {
return EmulationSession::GetInstance().SetScreenRotation(static_cast<u32>(rotation));
}
void Java_org_yuzu_yuzu_1emu_NativeLibrary_setAppDirectory(JNIEnv* env, void Java_org_yuzu_yuzu_1emu_NativeLibrary_setAppDirectory(JNIEnv* env,
[[maybe_unused]] jclass clazz, [[maybe_unused]] jclass clazz,
jstring j_directory) { jstring j_directory) {
@ -687,6 +654,12 @@ jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getCompany([[maybe_unused]] JNIEnv
return env->NewStringUTF(""); return env->NewStringUTF("");
} }
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_isHomebrew([[maybe_unused]] JNIEnv* env,
[[maybe_unused]] jclass clazz,
[[maybe_unused]] jstring j_filename) {
return EmulationSession::GetInstance().GetIsHomebrew(GetJString(env, j_filename));
}
void Java_org_yuzu_yuzu_1emu_NativeLibrary_initializeEmulation void Java_org_yuzu_yuzu_1emu_NativeLibrary_initializeEmulation
[[maybe_unused]] (JNIEnv* env, [[maybe_unused]] jclass clazz) { [[maybe_unused]] (JNIEnv* env, [[maybe_unused]] jclass clazz) {
// Create the default config.ini. // Create the default config.ini.
@ -796,45 +769,4 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_submitInlineKeyboardInput(JNIEnv* env
EmulationSession::GetInstance().SoftwareKeyboard()->SubmitInlineKeyboardInput(j_key_code); EmulationSession::GetInstance().SoftwareKeyboard()->SubmitInlineKeyboardInput(j_key_code);
} }
void Java_org_yuzu_yuzu_1emu_NativeLibrary_connectToRoom(JNIEnv* env, jclass clazz,
jstring nickname,
jstring server_addr,
jint server_port,
jstring password) {
EmulationSession::GetInstance().DirectConnectToRoom(
GetJString(env, nickname),
GetJString(env, server_addr).c_str(),
server_port,
GetJString(env, password)
);
}
jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getRoomMemberState(JNIEnv* env, jclass clazz) {
auto state = EmulationSession::GetInstance().GetRoomMemberState();
std::string state_str{};
switch(state) {
using State = Network::RoomMember::State;
case State::Uninitialized:
state_str = "Uninitialized";
break;
case State::Idle:
state_str = "Idle";
break;
case State::Joining:
state_str = "Joining";
break;
case State::Joined:
state_str = "Joined";
break;
case State::Moderator:
state_str = "Moderator";
break;
}
return env->NewStringUTF(state_str.c_str());
}
} // extern "C" } // extern "C"

View file

@ -33,7 +33,8 @@ static_assert(sizeof(NroSegmentHeader) == 0x8, "NroSegmentHeader has incorrect s
struct NroHeader { struct NroHeader {
INSERT_PADDING_BYTES(0x4); INSERT_PADDING_BYTES(0x4);
u32_le module_header_offset; u32_le module_header_offset;
INSERT_PADDING_BYTES(0x8); u32 magic_ext1;
u32 magic_ext2;
u32_le magic; u32_le magic;
INSERT_PADDING_BYTES(0x4); INSERT_PADDING_BYTES(0x4);
u32_le file_size; u32_le file_size;
@ -124,6 +125,16 @@ FileType AppLoader_NRO::IdentifyType(const FileSys::VirtualFile& nro_file) {
return FileType::Error; return FileType::Error;
} }
bool AppLoader_NRO::IsHomebrew() {
// Read NSO header
NroHeader nro_header{};
if (sizeof(NroHeader) != file->ReadObject(&nro_header)) {
return false;
}
return nro_header.magic_ext1 == Common::MakeMagic('H', 'O', 'M', 'E') &&
nro_header.magic_ext2 == Common::MakeMagic('B', 'R', 'E', 'W');
}
static constexpr u32 PageAlignSize(u32 size) { static constexpr u32 PageAlignSize(u32 size) {
return static_cast<u32>((size + Core::Memory::YUZU_PAGEMASK) & ~Core::Memory::YUZU_PAGEMASK); return static_cast<u32>((size + Core::Memory::YUZU_PAGEMASK) & ~Core::Memory::YUZU_PAGEMASK);
} }

View file

@ -38,6 +38,8 @@ public:
*/ */
static FileType IdentifyType(const FileSys::VirtualFile& nro_file); static FileType IdentifyType(const FileSys::VirtualFile& nro_file);
bool IsHomebrew();
FileType GetFileType() const override { FileType GetFileType() const override {
return IdentifyType(file); return IdentifyType(file);
} }

View file

@ -37,10 +37,6 @@
#include "video_core/vulkan_common/vulkan_memory_allocator.h" #include "video_core/vulkan_common/vulkan_memory_allocator.h"
#include "video_core/vulkan_common/vulkan_wrapper.h" #include "video_core/vulkan_common/vulkan_wrapper.h"
#ifdef ANDROID
extern u32 GetAndroidScreenRotation();
#endif
namespace Vulkan { namespace Vulkan {
namespace { namespace {
@ -78,47 +74,6 @@ struct ScreenRectVertex {
} }
}; };
#ifdef ANDROID
std::array<f32, 4 * 4> MakeOrthographicMatrix(f32 width, f32 height) {
constexpr u32 ROTATION_0 = 0;
constexpr u32 ROTATION_90 = 1;
constexpr u32 ROTATION_180 = 2;
constexpr u32 ROTATION_270 = 3;
// clang-format off
switch (GetAndroidScreenRotation()) {
case ROTATION_0:
// Desktop
return { 2.f / width, 0.f, 0.f, 0.f,
0.f, 2.f / height, 0.f, 0.f,
0.f, 0.f, 1.f, 0.f,
-1.f, -1.f, 0.f, 1.f};
case ROTATION_180:
// Reverse desktop
return {-2.f / width, 0.f, 0.f, 0.f,
0.f, -2.f / height, 0.f, 0.f,
0.f, 0.f, 1.f, 0.f,
1.f, 1.f, 0.f, 1.f};
case ROTATION_270:
// Reverse landscape
return { 0.f, -2.f / width, 0.f, 0.f,
2.f / height, 0.f, 0.f, 0.f,
0.f, 0.f, 1.f, 0.f,
-1.f, 1.f, 0.f, 1.f};
case ROTATION_90:
default:
// Landscape
return { 0.f, 2.f / width, 0.f, 0.f,
-2.f / height, 0.f, 0.f, 0.f,
0.f, 0.f, 1.f, 0.f,
1.f, -1.f, 0.f, 1.f};
}
// clang-format on
}
#else
std::array<f32, 4 * 4> MakeOrthographicMatrix(f32 width, f32 height) { std::array<f32, 4 * 4> MakeOrthographicMatrix(f32 width, f32 height) {
// clang-format off // clang-format off
return { 2.f / width, 0.f, 0.f, 0.f, return { 2.f / width, 0.f, 0.f, 0.f,
@ -128,8 +83,6 @@ std::array<f32, 4 * 4> MakeOrthographicMatrix(f32 width, f32 height) {
// clang-format on // clang-format on
} }
#endif
u32 GetBytesPerPixel(const Tegra::FramebufferConfig& framebuffer) { u32 GetBytesPerPixel(const Tegra::FramebufferConfig& framebuffer) {
using namespace VideoCore::Surface; using namespace VideoCore::Surface;
return BytesPerBlock(PixelFormatFromGPUPixelFormat(framebuffer.pixel_format)); return BytesPerBlock(PixelFormatFromGPUPixelFormat(framebuffer.pixel_format));
@ -1159,7 +1112,7 @@ void BlitScreen::CreateRawImages(const Tegra::FramebufferConfig& framebuffer) {
.pNext = nullptr, .pNext = nullptr,
.flags = 0, .flags = 0,
.imageType = VK_IMAGE_TYPE_2D, .imageType = VK_IMAGE_TYPE_2D,
.format = GetFormat(framebuffer), .format = used_on_framebuffer ? VK_FORMAT_R16G16B16A16_SFLOAT : GetFormat(framebuffer),
.extent = .extent =
{ {
.width = (up_scale * framebuffer.width) >> down_shift, .width = (up_scale * framebuffer.width) >> down_shift,
@ -1180,14 +1133,14 @@ void BlitScreen::CreateRawImages(const Tegra::FramebufferConfig& framebuffer) {
const auto create_commit = [&](vk::Image& image) { const auto create_commit = [&](vk::Image& image) {
return memory_allocator.Commit(image, MemoryUsage::DeviceLocal); return memory_allocator.Commit(image, MemoryUsage::DeviceLocal);
}; };
const auto create_image_view = [&](vk::Image& image) { const auto create_image_view = [&](vk::Image& image, bool used_on_framebuffer = false) {
return device.GetLogical().CreateImageView(VkImageViewCreateInfo{ return device.GetLogical().CreateImageView(VkImageViewCreateInfo{
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
.pNext = nullptr, .pNext = nullptr,
.flags = 0, .flags = 0,
.image = *image, .image = *image,
.viewType = VK_IMAGE_VIEW_TYPE_2D, .viewType = VK_IMAGE_VIEW_TYPE_2D,
.format = GetFormat(framebuffer), .format = used_on_framebuffer ? VK_FORMAT_R16G16B16A16_SFLOAT : GetFormat(framebuffer),
.components = .components =
{ {
.r = VK_COMPONENT_SWIZZLE_IDENTITY, .r = VK_COMPONENT_SWIZZLE_IDENTITY,
@ -1217,7 +1170,7 @@ void BlitScreen::CreateRawImages(const Tegra::FramebufferConfig& framebuffer) {
const u32 down_shift = Settings::values.resolution_info.down_shift; const u32 down_shift = Settings::values.resolution_info.down_shift;
aa_image = create_image(true, up_scale, down_shift); aa_image = create_image(true, up_scale, down_shift);
aa_commit = create_commit(aa_image); aa_commit = create_commit(aa_image);
aa_image_view = create_image_view(aa_image); aa_image_view = create_image_view(aa_image, true);
VkExtent2D size{ VkExtent2D size{
.width = (up_scale * framebuffer.width) >> down_shift, .width = (up_scale * framebuffer.width) >> down_shift,
.height = (up_scale * framebuffer.height) >> down_shift, .height = (up_scale * framebuffer.height) >> down_shift,

View file

@ -231,7 +231,12 @@ void Swapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities, bo
.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE, .imageSharingMode = VK_SHARING_MODE_EXCLUSIVE,
.queueFamilyIndexCount = 0, .queueFamilyIndexCount = 0,
.pQueueFamilyIndices = nullptr, .pQueueFamilyIndices = nullptr,
#ifdef ANDROID
// On Android, do not allow surface rotation to deviate from the frontend.
.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR,
#else
.preTransform = capabilities.currentTransform, .preTransform = capabilities.currentTransform,
#endif
.compositeAlpha = alpha_flags, .compositeAlpha = alpha_flags,
.presentMode = present_mode, .presentMode = present_mode,
.clipped = VK_FALSE, .clipped = VK_FALSE,

View file

@ -760,6 +760,7 @@ void Config::ReadRendererValues() {
ReadGlobalSetting(Settings::values.use_fast_gpu_time); ReadGlobalSetting(Settings::values.use_fast_gpu_time);
ReadGlobalSetting(Settings::values.use_vulkan_driver_pipeline_cache); ReadGlobalSetting(Settings::values.use_vulkan_driver_pipeline_cache);
ReadGlobalSetting(Settings::values.enable_compute_pipelines); ReadGlobalSetting(Settings::values.enable_compute_pipelines);
ReadGlobalSetting(Settings::values.use_video_framerate);
ReadGlobalSetting(Settings::values.bg_red); ReadGlobalSetting(Settings::values.bg_red);
ReadGlobalSetting(Settings::values.bg_green); ReadGlobalSetting(Settings::values.bg_green);
ReadGlobalSetting(Settings::values.bg_blue); ReadGlobalSetting(Settings::values.bg_blue);
@ -1415,6 +1416,7 @@ void Config::SaveRendererValues() {
WriteGlobalSetting(Settings::values.use_fast_gpu_time); WriteGlobalSetting(Settings::values.use_fast_gpu_time);
WriteGlobalSetting(Settings::values.use_vulkan_driver_pipeline_cache); WriteGlobalSetting(Settings::values.use_vulkan_driver_pipeline_cache);
WriteGlobalSetting(Settings::values.enable_compute_pipelines); WriteGlobalSetting(Settings::values.enable_compute_pipelines);
WriteGlobalSetting(Settings::values.use_video_framerate);
WriteGlobalSetting(Settings::values.bg_red); WriteGlobalSetting(Settings::values.bg_red);
WriteGlobalSetting(Settings::values.bg_green); WriteGlobalSetting(Settings::values.bg_green);
WriteGlobalSetting(Settings::values.bg_blue); WriteGlobalSetting(Settings::values.bg_blue);