Skip to content

Commit

Permalink
updated gamesurfacelayer and settings for immersive mode (not sure ye…
Browse files Browse the repository at this point in the history
…t if 5 is a special constant or based on resolution)
  • Loading branch information
amwatson committed Jan 25, 2024
1 parent 1d92111 commit 47186f0
Show file tree
Hide file tree
Showing 20 changed files with 94 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -432,9 +432,10 @@ private void addVRSettings(ArrayList<SettingsItem> sl) {
Setting vrEnvironment = vrSection.getSetting(SettingsFile.KEY_VR_ENVIRONMENT);
Setting vrExtraPerformanceMode = vrSection.getSetting(SettingsFile.KEY_VR_EXTRA_PERFORMANCE_MODE);
Setting vrCpuLevel = vrSection.getSetting(SettingsFile.KEY_VR_CPU_LEVEL);
Setting vrImmersiveMode = vrSection.getSetting(SettingsFile.KEY_VR_IMMERSIVE_MODE);
sl.add(new SingleChoiceSetting(SettingsFile.KEY_VR_ENVIRONMENT, Settings.SECTION_VR, R.string.vr_background, 0, R.array.vrBackgroundNames, R.array.vrBackgroundValues, VRUtils.getHMDType() == VRUtils.HMDType.QUEST3.getValue() ? 1 : 2, vrEnvironment));
sl.add(new CheckBoxSetting(SettingsFile.KEY_VR_EXTRA_PERFORMANCE_MODE, Settings.SECTION_VR, R.string.vr_extra_performance_mode, R.string.vr_extra_performance_mode_description, false, vrExtraPerformanceMode));
sl.add(new SingleChoiceSetting(SettingsFile.KEY_VR_CPU_LEVEL, Settings.SECTION_VR, R.string.vr_cpu_level, R.string.vr_cpu_level_description, R.array.vrCpuLevelNames, R.array.vrCpuLevelValues, 4, vrCpuLevel));

sl.add(new CheckBoxSetting(SettingsFile.KEY_VR_IMMERSIVE_MODE, Settings.SECTION_VR, R.string.vr_immersive_mode_title, R.string.vr_immersive_mode_description, false, vrImmersiveMode));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -133,9 +133,9 @@ public final class SettingsFile {
public static final String KEY_CAMERA_INNER_FLIP = "camera_inner_flip";
public static final String KEY_VR_ENVIRONMENT = "vr_environment";
public static final String KEY_VR_EXTRA_PERFORMANCE_MODE = "vr_extra_performance_mode";

public static final String KEY_VR_CPU_LEVEL = "vr_cpu_level";

public static final String KEY_VR_IMMERSIVE_MODE = "vr_immersive_mode";
public static final String KEY_LOG_FILTER = "log_filter";

private static BiMap<String, String> sectionsMap = new BiMap<>();
Expand Down
15 changes: 14 additions & 1 deletion src/android/app/src/main/jni/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -301,11 +301,24 @@ void Config::ReadValues() {
"VR", "vr_environment",
static_cast<long>(VRSettings::values.hmd_type == VRSettings::HMDType::QUEST3 ?
VRSettings::VREnvironmentType::PASSTHROUGH : VRSettings::VREnvironmentType::VOID));

VRSettings::values.cpu_level =
VRSettings::values.extra_performance_mode_enabled ? XR_HIGHEST_CPU_PERF_LEVEL
: VRSettings::CPUPrefToPerfSettingsLevel(sdl2_config->GetInteger(
"VR", "vr_cpu_level", XR_HIGHEST_CPU_PREFERENCE));
VRSettings::values.vr_immersive_mode_enabled = sdl2_config->GetBoolean(
"VR", "vr_immersive_mode", false);
Settings::values.vr_immersive_mode_enabled = VRSettings::values.vr_immersive_mode_enabled;

if (VRSettings::values.vr_immersive_mode_enabled) {
LOG_INFO(Config, "VR immersive mode enabled");
// Math was done using resolution factor 5, so if resolution is always 5x in
// immersive mode, I can avoid generalizing.
VRSettings::values.resolution_factor = 5;
// no point rendering passthrough in immersive mode
VRSettings::values.vr_environment =
static_cast<uint32_t>(VRSettings::VREnvironmentType::VOID);
}


// Miscellaneous
ReadSetting("Miscellaneous", Settings::values.log_filter);
Expand Down
28 changes: 20 additions & 8 deletions src/android/app/src/main/jni/vr/layers/GameSurfaceLayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ License : Licensed under GPLv3 or any later version.

#include "GameSurfaceLayer.h"

#include "../vr_settings.h"

#include "../utils/JniUtils.h"
#include "../utils/LogUtils.h"
#include "../utils/SyspropUtils.h"
Expand Down Expand Up @@ -223,9 +225,15 @@ GameSurfaceLayer::GameSurfaceLayer(const XrVector3f&& position, JNIEnv* env, job
const XrSession& session, const uint32_t resolutionFactor)
: session_(session), topPanelFromWorld_(CreateTopPanelFromWorld(position)),
lowerPanelFromWorld_(CreateLowerPanelFromWorld(topPanelFromWorld_)),
resolutionFactor_(resolutionFactor), env_(env), activityObject_(activityObject)
resolutionFactor_(resolutionFactor),
useImmersiveMode_(VRSettings::values.vr_immersive_mode_enabled), env_(env),
activityObject_(activityObject)

{
if (useImmersiveMode_) {
ALOGI("Using immersive mode");
topPanelFromWorld_.position.z = lowerPanelFromWorld_.position.z;
}
const int32_t initializationStatus = Init(activityObject, position, session);
if (initializationStatus < 0) {
FAIL("Could not initialize GameSurfaceLayer -- error '%d'", initializationStatus);
Expand All @@ -252,8 +260,8 @@ void GameSurfaceLayer::Frame(const XrSpace& space, std::vector<XrCompositionLaye
static_cast<double>(2 * panelWidth) / static_cast<double>(panelHeight);
// Prevent a seam between the top and bottom view
constexpr uint32_t verticalBorderTex = 1;
const int32_t useCylinder = GetCylinderSysprop();
if (useCylinder == 1) {
const bool useCylinder = (GetCylinderSysprop() != 0) || useImmersiveMode_;
if (useCylinder) {

// Create the Top Display Panel (Curved display)
for (uint32_t eye = 0; eye < NUM_EYES; eye++) {
Expand Down Expand Up @@ -284,7 +292,8 @@ void GameSurfaceLayer::Frame(const XrSpace& space, std::vector<XrCompositionLaye
// scale of the texture.
const float radius = GetRadiusSysprop();
layer.radius = radius;
layer.centralAngle = GetCentralAngleSysprop() * MATH_FLOAT_PI / 180.0f;
layer.centralAngle = (!useImmersiveMode_ ? GetCentralAngleSysprop() : 55.0f * 5.0f) *
MATH_FLOAT_PI / 180.0f;
layer.aspectRatio = -aspectRatio;
layers[layerCount++].mCylinder = layer;
}
Expand Down Expand Up @@ -343,10 +352,13 @@ void GameSurfaceLayer::Frame(const XrSpace& space, std::vector<XrCompositionLaye
layer.eyeVisibility = XR_EYE_VISIBILITY_BOTH;
memset(&layer.subImage, 0, sizeof(XrSwapchainSubImage));
layer.subImage.swapchain = swapchain_.Handle;
layer.subImage.imageRect.offset.x = cropHoriz / 2;
layer.subImage.imageRect.offset.y = panelHeight + verticalBorderTex;
layer.subImage.imageRect.extent.width = panelWidth - cropHoriz;
layer.subImage.imageRect.extent.height = panelHeight;
layer.subImage.imageRect.offset.x =
!useImmersiveMode_ ? cropHoriz / 2 : (90/2) * resolutionFactor_ / 5 + 2 * panelWidth / 5;;
layer.subImage.imageRect.offset.y =
!useImmersiveMode_ ? panelHeight + verticalBorderTex
: panelHeight + verticalBorderTex + 2 * panelWidth / 5 - 4 * 5;
layer.subImage.imageRect.extent.width = !useImmersiveMode_ ? panelWidth - cropHoriz : (panelWidth - 90 * resolutionFactor_) / 5;
layer.subImage.imageRect.extent.height = !useImmersiveMode_ ? panelHeight : panelHeight / 5;
layer.subImage.imageArrayIndex = 0;
layer.pose = lowerPanelFromWorld_;
const auto scale = GetDensityScaleForSize(panelWidth - cropHoriz, -panelHeight,
Expand Down
3 changes: 3 additions & 0 deletions src/android/app/src/main/jni/vr/layers/GameSurfaceLayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,9 @@ class GameSurfaceLayer {
// resolution.
const uint32_t resolutionFactor_;

// When true, top screen is projected onto a 180-degree cylinder.
const bool useImmersiveMode_;

//============================
// JNI objects
JNIEnv* env_ = nullptr;
Expand Down
14 changes: 6 additions & 8 deletions src/android/app/src/main/jni/vr/vr_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -895,14 +895,12 @@ extern "C" JNIEXPORT void JNICALL Java_org_citra_citra_1emu_vr_ErrorMessageLayer
gShouldShowErrorMessage = should_show_error;
}

extern "C"
JNIEXPORT jint JNICALL
Java_org_citra_citra_1emu_vr_VRUtils_getHMDType(JNIEnv *env, jclass clazz) {
extern "C" JNIEXPORT jint JNICALL Java_org_citra_citra_1emu_vr_VRUtils_getHMDType(JNIEnv* env,
jclass clazz) {
return static_cast<jint>(VRSettings::HmdTypeFromStr(VRSettings::GetHMDTypeStr()));
}
extern "C"
JNIEXPORT jint JNICALL
Java_org_citra_citra_1emu_vr_VRUtils_getDefaultResolutionFactor(JNIEnv *env, jclass clazz) {
const VRSettings::HMDType hmdType = VRSettings::HmdTypeFromStr(VRSettings::GetHMDTypeStr());
return GetDefaultGameResolutionFactorForHmd(hmdType);
extern "C" JNIEXPORT jint JNICALL
Java_org_citra_citra_1emu_vr_VRUtils_getDefaultResolutionFactor(JNIEnv* env, jclass clazz) {
const VRSettings::HMDType hmdType = VRSettings::HmdTypeFromStr(VRSettings::GetHMDTypeStr());
return GetDefaultGameResolutionFactorForHmd(hmdType);
}
7 changes: 4 additions & 3 deletions src/android/app/src/main/jni/vr/vr_settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,12 @@ std::string GetHMDTypeStr();
HMDType HmdTypeFromStr(const std::string& hmdType);

struct Values {
bool extra_performance_mode_enabled = false;
int32_t vr_environment = 0;
XrPerfSettingsLevelEXT cpu_level = XR_HIGHEST_CPU_PERF_LEVEL;
uint32_t resolution_factor = 0;
HMDType hmd_type = HMDType::UNKNOWN;
uint32_t resolution_factor = 0;
int32_t vr_environment = 0;
bool extra_performance_mode_enabled = false;
bool vr_immersive_mode_enabled = false;
} extern values;

} // namespace VRSettings
2 changes: 2 additions & 0 deletions src/android/app/src/main/res/values-de/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -173,4 +173,6 @@
<string name="vr_extra_performance_mode">VR zusätzlicher Leistungsmodus</string>
<string name="vr_cpu_level">CPU -Ebene</string>
<string name="vr_cpu_level_description">Höhere Werte können die Audio-/Emulationsleistung verbessern, die Batterie jedoch schneller abtropfen lassen</string>
<string name="vr_immersive_mode_title">Experimentell: Immersive Modus</string>
<string name="vr_immersive_mode_description">Verzerrt den oberen Bildschirm um einen Zylinder für das Gameplay im VR180-Stil</string>
</resources>
2 changes: 2 additions & 0 deletions src/android/app/src/main/res/values-es/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -177,4 +177,6 @@
<string name="vr_extra_performance_mode">Modo de rendimiento adicional VR</string>
<string name="vr_cpu_level">Nivel de la CPU</string>
<string name="vr_cpu_level_description">Los niveles más altos pueden mejorar el rendimiento de audio/emulación, pero drenarán la batería más rápido</string>
<string name="vr_immersive_mode_title">Experimental: modo inmersivo</string>
<string name="vr_immersive_mode_description">Deforma la pantalla superior alrededor de un cilindro para el juego al estilo VR180</string>
</resources>
2 changes: 2 additions & 0 deletions src/android/app/src/main/res/values-fi/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -101,4 +101,6 @@
<string name="vr_extra_performance_mode">VR Extra Performance -tila</string>
<string name="vr_cpu_level">CPU -taso</string>
<string name="vr_cpu_level_description">Korkeammat tasot voivat parantaa audio/emulointia, mutta tyhjentää akun nopeammin</string>
<string name="vr_immersive_mode_title">Kokeellinen: Syventävä tila</string>
<string name="vr_immersive_mode_description">Vältä yläreunan sylinterin ympärillä VR180-tyyliseen pelin peliin</string>
</resources>
2 changes: 2 additions & 0 deletions src/android/app/src/main/res/values-fr/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -173,4 +173,6 @@
<string name="vr_extra_performance_mode">Mode de performance supplémentaire VR</string>
<string name="vr_cpu_level">Niveau du processeur</string>
<string name="vr_cpu_level_description">Des niveaux plus élevés peuvent améliorer les performances audio / émulation, mais draineront la batterie plus rapidement</string>
<string name="vr_immersive_mode_title">Expérimental: mode immersif</string>
<string name="vr_immersive_mode_description">Déforme l\'écran supérieur autour d\'un cylindre pour le gameplay de style VR180</string>
</resources>
2 changes: 2 additions & 0 deletions src/android/app/src/main/res/values-it/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -173,4 +173,6 @@
<string name="vr_extra_performance_mode">Modalità di prestazione extra VR</string>
<string name="vr_cpu_level">Livello CPU</string>
<string name="vr_cpu_level_description">Livelli più alti possono migliorare le prestazioni audio/emulazione, ma prosciugheranno la batteria più velocemente</string>
<string name="vr_immersive_mode_title">Sperimentale: modalità immersiva</string>
<string name="vr_immersive_mode_description">Decidere lo schermo superiore attorno a un cilindro per il gameplay in stile VR180</string>
</resources>
2 changes: 2 additions & 0 deletions src/android/app/src/main/res/values-ja/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -118,4 +118,6 @@
<string name="vr_extra_performance_mode">VR追加パフォーマンスモード</string>
<string name="vr_cpu_level">CPUレベル</string>
<string name="vr_cpu_level_description">より高いレベルはオーディオ/エミュレーションのパフォーマンスを改善する可能性がありますが、バッテリーをより速く排出します</string>
<string name="vr_immersive_mode_title">実験:没入モード</string>
<string name="vr_immersive_mode_description">VR180スタイルのゲームプレイ用のシリンダーの周りのトップ画面をゆがめます</string>
</resources>
2 changes: 2 additions & 0 deletions src/android/app/src/main/res/values-ko/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -175,4 +175,6 @@
<string name="vr_extra_performance_mode">VR 추가 성능 모드</string>
<string name="vr_cpu_level">CPU 레벨</string>
<string name="vr_cpu_level_description">레벨이 높을수록 오디오/에뮬레이션 성능이 향상 될 수 있지만 배터리가 더 빨리 배터리를 배출합니다. </string>
<string name="vr_immersive_mode_title">실험 : 몰입 형 모드</string>
<string name="vr_immersive_mode_description">VR180 스타일의 게임 플레이를 위해 실린더 주위에 상단 화면을 날려</string>
</resources>
2 changes: 2 additions & 0 deletions src/android/app/src/main/res/values-nb/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -173,4 +173,6 @@
<string name="vr_extra_performance_mode">VR Extra Performance Mode</string>
<string name="vr_cpu_level">CPU -nivå</string>
<string name="vr_cpu_level_description">Høyere nivåer kan forbedre ytelsen til lyd/emulering, men vil tømme batteriet raskere</string>
<string name="vr_immersive_mode_title">Eksperimentell: oppslukende modus</string>
<string name="vr_immersive_mode_description">Varger toppskjermen rundt en sylinder for VR180-stil gameplay</string>
</resources>
2 changes: 2 additions & 0 deletions src/android/app/src/main/res/values-pt/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -173,4 +173,6 @@
<string name="vr_extra_performance_mode">VR Modo de desempenho extra</string>
<string name="vr_cpu_level">Nível da CPU</string>
<string name="vr_cpu_level_description">Níveis mais altos podem melhorar o desempenho de áudio/emulação, mas drenará a bateria mais rapidamente</string>
<string name="vr_immersive_mode_title">Experimental: modo imersivo</string>
<string name="vr_immersive_mode_description">Distorce a tela superior em torno de um cilindro para jogabilidade no estilo VR180</string>
</resources>
2 changes: 2 additions & 0 deletions src/android/app/src/main/res/values-zh/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -173,4 +173,6 @@
<string name="vr_extra_performance_mode">VR额外的性能模式</string>
<string name="vr_cpu_level">CPU级别</string>
<string name="vr_cpu_level_description">较高的水平可以改善音频/仿真性能,但会更快地排出电池</string>
<string name="vr_immersive_mode_title">实验:沉浸式模式</string>
<string name="vr_immersive_mode_description">在VR180风格的游戏玩家的圆柱体周围扭曲顶部屏幕</string>
</resources>
2 changes: 2 additions & 0 deletions src/android/app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -300,4 +300,6 @@
<string name="vr_extra_performance_mode">VR Extra Performance Mode</string>
<string name="vr_cpu_level">CPU level</string>
<string name="vr_cpu_level_description">Higher levels may improve audio/emulation performance, but will drain the battery faster</string>
<string name="vr_immersive_mode_title">Experimental: Immersive Mode</string>
<string name="vr_immersive_mode_description">Warps the top screen around a cylinder for VR180-style gameplay</string>
</resources>
3 changes: 3 additions & 0 deletions src/common/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,9 @@ struct Values {
std::string audio_encoder;
std::string audio_encoder_options;
u64 audio_bitrate;

// VR
bool vr_immersive_mode_enabled;
};

extern Values values;
Expand Down
22 changes: 19 additions & 3 deletions src/video_core/shader/generator/glsl_shader_gen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "video_core/shader/generator/glsl_shader_decompiler.h"
#include "video_core/shader/generator/glsl_shader_gen.h"
#include "video_core/shader/generator/shader_uniforms.h"
#include "common/settings.h"

using Pica::FramebufferRegs;
using Pica::LightingRegs;
Expand Down Expand Up @@ -1678,8 +1679,13 @@ void main() {
if (abs(vtx_pos.z) < EPSILON_Z) {
vtx_pos.z = 0.f;
}
gl_Position = vec4(vtx_pos.x, vtx_pos.y, -vtx_pos.z, vtx_pos.w);
)";

if (Settings::values.vr_immersive_mode_enabled) {
out+= "\ngl_Position = vec4(vtx_pos.x / 5.0, vtx_pos.y / 5.0, -vtx_pos.z, vtx_pos.w);\n";
} else {
out+= "\ngl_Position = vec4(vtx_pos.x, vtx_pos.y, -vtx_pos.z, vtx_pos.w);\n";
}
if (use_clip_planes) {
out += R"(
gl_ClipDistance[0] = -vtx_pos.z; // fixed PICA clipping plane z <= 0
Expand Down Expand Up @@ -1796,7 +1802,11 @@ std::string GenerateVertexShader(const Pica::Shader::ShaderSetup& setup, const P
out += " if (abs(vtx_pos.z) < EPSILON_Z) {\n";
out += " vtx_pos.z = 0.f;\n";
out += " }\n";
out += " gl_Position = vec4(vtx_pos.x, vtx_pos.y, -vtx_pos.z, vtx_pos.w);\n";
if (Settings::values.vr_immersive_mode_enabled) {
out += " gl_Position = vec4(vtx_pos.x / 5.0, vtx_pos.y / 5.0, -vtx_pos.z, vtx_pos.w);\n";
} else {
out += " gl_Position = vec4(vtx_pos.x, vtx_pos.y, -vtx_pos.z, vtx_pos.w);\n";
}
if (config.state.use_clip_planes) {
out += " gl_ClipDistance[0] = -vtx_pos.z;\n"; // fixed PICA clipping plane z <= 0
out += " if (enable_clip1) {\n";
Expand Down Expand Up @@ -1893,7 +1903,13 @@ struct Vertex {
out += " if (abs(vtx_pos.z) < EPSILON_Z) {\n";
out += " vtx_pos.z = 0.f;\n";
out += " }\n";
out += " gl_Position = vec4(vtx_pos.x, vtx_pos.y, -vtx_pos.z, vtx_pos.w);\n";

if (Settings::values.vr_immersive_mode_enabled) {
out += " gl_Position = vec4(vtx_pos.x / 5.0, vtx_pos.y / 5.0, -vtx_pos.z, vtx_pos.w);\n";
} else {
out += " gl_Position = vec4(vtx_pos.x, vtx_pos.y, -vtx_pos.z, vtx_pos.w);\n";
}

if (state.use_clip_planes) {
out += " gl_ClipDistance[0] = -vtx_pos.z;\n"; // fixed PICA clipping plane z <= 0
out += " if (enable_clip1) {\n";
Expand Down

1 comment on commit 47186f0

@lvonasek
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey, great work on this. I am sorry I didn't manage to make a PR myself.

Few suggestions I have:

  • Do not hardcode 5 in the code. It could be 2-5 depending on how much immersion user wants to have (6 is already too much because the geometry gets way too wrong there).
  • Do not downscale the geometry for the touch screen (currently it just downscales on shader and "upscales" in the layer).
  • Inform user than the immersion mode required adjusting the depth slider and maybe the internal resolution.
  • Possible fix for some effects could be to adjust UV coordinates when the input texture is a framebuffer.

Other way, feel free to use it as you want. I do not have any copyright on this ;-)

I tested this on PPSSPP and it didn't work (the geometry culling is way too strict). On Dolphin it worked on a few games but there I need to resolve the adjustment of the UV coordinates as mentioned above (there is rarely a game where the effect glitches are okay).

Please sign in to comment.