rsx: allow to toggle 3D modes dynamically
Some checks are pending
Generate Translation Template / Generate Translation Template (push) Waiting to run
Build RPCS3 / RPCS3 Linux ${{ matrix.os }} ${{ matrix.compiler }} (/rpcs3/.ci/build-linux-aarch64.sh, gcc, rpcs3/rpcs3-ci-jammy-aarch64:1.6, ubuntu-24.04-arm) (push) Waiting to run
Build RPCS3 / RPCS3 Linux ${{ matrix.os }} ${{ matrix.compiler }} (/rpcs3/.ci/build-linux.sh, gcc, rpcs3/rpcs3-ci-jammy:1.6, ubuntu-24.04) (push) Waiting to run
Build RPCS3 / RPCS3 Linux ${{ matrix.os }} ${{ matrix.compiler }} (a1d35836e8d45bfc6f63c26f0a3e5d46ef622fe1, rpcs3/rpcs3-binaries-linux-arm64, /rpcs3/.ci/build-linux-aarch64.sh, clang, rpcs3/rpcs3-ci-jammy-aarch64:1.6, ubuntu-24.04-arm) (push) Waiting to run
Build RPCS3 / RPCS3 Linux ${{ matrix.os }} ${{ matrix.compiler }} (d812f1254a1157c80fd402f94446310560f54e5f, rpcs3/rpcs3-binaries-linux, /rpcs3/.ci/build-linux.sh, clang, rpcs3/rpcs3-ci-jammy:1.6, ubuntu-24.04) (push) Waiting to run
Build RPCS3 / RPCS3 Mac ${{ matrix.name }} (51ae32f468089a8169aaf1567de355ff4a3e0842, rpcs3/rpcs3-binaries-mac, arch -X86_64 .ci/build-mac.sh, Intel) (push) Waiting to run
Build RPCS3 / RPCS3 Mac ${{ matrix.name }} (8e21bdbc40711a3fccd18fbf17b742348b0f4281, rpcs3/rpcs3-binaries-mac-arm64, .ci/build-mac-arm64.sh, Apple Silicon) (push) Waiting to run
Build RPCS3 / RPCS3 Windows (push) Waiting to run
Build RPCS3 / RPCS3 Windows Clang (win64, clang, clang64) (push) Waiting to run
Build RPCS3 / RPCS3 FreeBSD (push) Waiting to run

A new checkbox for 3D support needs to be enabled at boot though.
This commit is contained in:
Megamouse 2025-09-12 03:14:30 +02:00
parent 6106e8f79f
commit 0daa6d6fb0
19 changed files with 71 additions and 44 deletions

View file

@ -520,7 +520,7 @@ error_code cellVideoOutGetScreenSize(u32 videoOut, vm::ptr<f32> screenSize)
return CELL_VIDEO_OUT_ERROR_UNSUPPORTED_VIDEO_OUT;
}
if (g_cfg.video.stereo_render_mode != stereo_render_mode_options::disabled)
if (g_cfg.video.stereo_enabled)
{
// Return Playstation 3D display value
// Some games call this function when 3D is enabled

View file

@ -202,7 +202,7 @@ error_code cellVideoOutConfigure(u32 videoOut, vm::ptr<CellVideoOutConfiguration
CellVideoOutResolution res;
if (_IntGetResolutionInfo(config->resolutionId, &res) != CELL_OK ||
(config->resolutionId >= CELL_VIDEO_OUT_RESOLUTION_720_3D_FRAME_PACKING && g_cfg.video.stereo_render_mode == stereo_render_mode_options::disabled))
(config->resolutionId >= CELL_VIDEO_OUT_RESOLUTION_720_3D_FRAME_PACKING && !g_cfg.video.stereo_enabled))
{
// Resolution not supported
cellSysutil.error("Unusual resolution requested: 0x%x", config->resolutionId);
@ -211,7 +211,7 @@ error_code cellVideoOutConfigure(u32 videoOut, vm::ptr<CellVideoOutConfiguration
auto& conf = g_fxo->get<rsx::avconf>();
conf.resolution_id = config->resolutionId;
conf.stereo_mode = (config->resolutionId >= CELL_VIDEO_OUT_RESOLUTION_720_3D_FRAME_PACKING) ? g_cfg.video.stereo_render_mode.get() : stereo_render_mode_options::disabled;
conf.stereo_enabled = (config->resolutionId >= CELL_VIDEO_OUT_RESOLUTION_720_3D_FRAME_PACKING) && g_cfg.video.stereo_enabled;
conf.aspect = config->aspect;
conf.format = config->format;
conf.scanline_pitch = config->pitch;
@ -393,7 +393,7 @@ error_code cellVideoOutGetDeviceInfo(u32 videoOut, u32 deviceIndex, vm::ptr<Cell
break;
}
if (g_cfg.video.stereo_render_mode != stereo_render_mode_options::disabled && g_cfg.video.resolution == video_resolution::_720p)
if (g_cfg.video.stereo_enabled && g_cfg.video.resolution == video_resolution::_720p)
{
// Register 3D-capable display mode
if (true) // TODO
@ -454,7 +454,7 @@ error_code cellVideoOutGetResolutionAvailability(u32 videoOut, u32 resolutionId,
return not_an_error(1);
}
if ((g_cfg.video.stereo_render_mode != stereo_render_mode_options::disabled) && g_cfg.video.resolution == video_resolution::_720p)
if (g_cfg.video.stereo_enabled && g_cfg.video.resolution == video_resolution::_720p)
{
switch (resolutionId)
{

View file

@ -487,7 +487,8 @@ namespace gl
m_input_filter = gl::filter::linear;
}
void video_out_calibration_pass::run(gl::command_context& cmd, const areau& viewport, const rsx::simple_array<GLuint>& source, f32 gamma, bool limited_rgb, stereo_render_mode_options stereo_mode, gl::filter input_filter)
void video_out_calibration_pass::run(gl::command_context& cmd, const areau& viewport, const rsx::simple_array<GLuint>& source, f32 gamma, bool limited_rgb,
bool stereo_enabled, stereo_render_mode_options stereo_mode, gl::filter input_filter)
{
if (m_input_filter != input_filter)
{
@ -498,7 +499,7 @@ namespace gl
program_handle.uniforms["gamma"] = gamma;
program_handle.uniforms["limit_range"] = limited_rgb + 0;
program_handle.uniforms["stereo_display_mode"] = static_cast<u8>(stereo_mode);
program_handle.uniforms["stereo_display_mode"] = stereo_enabled ? static_cast<u8>(stereo_mode) : 0;
program_handle.uniforms["stereo_image_count"] = (source[1] == GL_NONE? 1 : 2);
saved_sampler_state saved(GL_TEMP_IMAGE_SLOT(0), m_sampler);

View file

@ -97,7 +97,8 @@ namespace gl
{
video_out_calibration_pass();
void run(gl::command_context& cmd, const areau& viewport, const rsx::simple_array<GLuint>& source, f32 gamma, bool limited_rgb, stereo_render_mode_options stereo_mode, gl::filter input_filter);
void run(gl::command_context& cmd, const areau& viewport, const rsx::simple_array<GLuint>& source, f32 gamma, bool limited_rgb,
bool stereo_enabled, stereo_render_mode_options stereo_mode, gl::filter input_filter);
};
struct rp_ssbo_to_generic_texture final : public overlay_pass

View file

@ -221,7 +221,7 @@ void GLGSRender::flip(const rsx::display_flip_info_t& info)
image_to_flip = get_present_source(&present_info, avconfig);
if (avconfig.stereo_mode != stereo_render_mode_options::disabled) [[unlikely]]
if (avconfig.stereo_enabled) [[unlikely]]
{
const auto [unused, min_expected_height] = rsx::apply_resolution_scale<true>(RSX_SURFACE_DIMENSION_IGNORED, buffer_height + 30);
if (image_to_flip->height() < min_expected_height)
@ -323,7 +323,7 @@ void GLGSRender::flip(const rsx::display_flip_info_t& info)
}
}
if (!backbuffer_has_alpha && use_full_rgb_range_output && rsx::fcmp(avconfig.gamma, 1.f) && avconfig.stereo_mode == stereo_render_mode_options::disabled)
if (!backbuffer_has_alpha && use_full_rgb_range_output && rsx::fcmp(avconfig.gamma, 1.f) && !avconfig.stereo_enabled)
{
// Blit source image to the screen
m_upscaler->scale_output(cmd, image_to_flip, screen_area, aspect_ratio.flipped_vertical(), UPSCALE_AND_COMMIT | UPSCALE_DEFAULT_VIEW);
@ -335,7 +335,7 @@ void GLGSRender::flip(const rsx::display_flip_info_t& info)
const auto filter = m_output_scaling == output_scaling_mode::nearest ? gl::filter::nearest : gl::filter::linear;
rsx::simple_array<gl::texture*> images{ image_to_flip, image_to_flip2 };
if (m_output_scaling == output_scaling_mode::fsr && avconfig.stereo_mode == stereo_render_mode_options::disabled) // 3D will be implemented later
if (m_output_scaling == output_scaling_mode::fsr && !avconfig.stereo_enabled) // 3D will be implemented later
{
for (unsigned i = 0; i < 2 && images[i]; ++i)
{
@ -345,7 +345,7 @@ void GLGSRender::flip(const rsx::display_flip_info_t& info)
}
gl::screen.bind();
m_video_output_pass.run(cmd, areau(aspect_ratio), images.map(FN(x ? x->id() : GL_NONE)), gamma, limited_range, avconfig.stereo_mode, filter);
m_video_output_pass.run(cmd, areau(aspect_ratio), images.map(FN(x ? x->id() : GL_NONE)), gamma, limited_range, avconfig.stereo_enabled, g_cfg.video.stereo_render_mode, filter);
}
}

View file

@ -49,6 +49,11 @@ namespace rsx
add_checkbox(&g_cfg.video.stretch_to_display_area, localized_string_id::HOME_MENU_SETTINGS_VIDEO_STRETCH_TO_DISPLAY);
if (g_cfg.video.stereo_enabled)
{
add_dropdown(&g_cfg.video.stereo_render_mode, localized_string_id::HOME_MENU_SETTINGS_VIDEO_STEREO_MODE);
}
apply_layout();
}

View file

@ -737,7 +737,7 @@ namespace rsx
return;
}
ar(stereo_mode, format, aspect, resolution_id, scanline_pitch, gamma, resolution_x, resolution_y, state, scan_mode);
ar(stereo_enabled, format, aspect, resolution_id, scanline_pitch, gamma, resolution_x, resolution_y, state, scan_mode);
}
void thread::capture_frame(const std::string& name)

View file

@ -894,11 +894,12 @@ namespace vk
}
void video_out_calibration_pass::run(vk::command_buffer& cmd, const areau& viewport, vk::framebuffer* target,
const rsx::simple_array<vk::viewable_image*>& src, f32 gamma, bool limited_rgb, stereo_render_mode_options stereo_mode, VkRenderPass render_pass)
const rsx::simple_array<vk::viewable_image*>& src, f32 gamma, bool limited_rgb,
bool stereo_enabled, stereo_render_mode_options stereo_mode, VkRenderPass render_pass)
{
config.gamma = gamma;
config.limit_range = limited_rgb? 1 : 0;
config.stereo_display_mode = static_cast<u8>(stereo_mode);
config.stereo_display_mode = stereo_enabled ? static_cast<u8>(stereo_mode) : 0;
config.stereo_image_count = std::min(::size32(src), 2u);
std::vector<vk::image_view*> views;

View file

@ -220,7 +220,8 @@ namespace vk
void update_uniforms(vk::command_buffer& cmd, vk::glsl::program* /*program*/) override;
void run(vk::command_buffer& cmd, const areau& viewport, vk::framebuffer* target,
const rsx::simple_array<vk::viewable_image*>& src, f32 gamma, bool limited_rgb, stereo_render_mode_options stereo_mode, VkRenderPass render_pass);
const rsx::simple_array<vk::viewable_image*>& src, f32 gamma, bool limited_rgb,
bool stereo_enabled, stereo_render_mode_options stereo_mode, VkRenderPass render_pass);
};
// TODO: Replace with a proper manager

View file

@ -483,7 +483,7 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info)
};
image_to_flip = get_present_source(&present_info, avconfig);
if (avconfig.stereo_mode != stereo_render_mode_options::disabled) [[unlikely]]
if (avconfig.stereo_enabled) [[unlikely]]
{
const auto [unused, min_expected_height] = rsx::apply_resolution_scale<true>(RSX_SURFACE_DIMENSION_IGNORED, buffer_height + 30);
if (image_to_flip->height() < min_expected_height)
@ -617,12 +617,12 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info)
{
const bool use_full_rgb_range_output = g_cfg.video.full_rgb_range_output.get();
if (!use_full_rgb_range_output || !rsx::fcmp(avconfig.gamma, 1.f) || avconfig.stereo_mode != stereo_render_mode_options::disabled) [[unlikely]]
if (!use_full_rgb_range_output || !rsx::fcmp(avconfig.gamma, 1.f) || avconfig.stereo_enabled) [[unlikely]]
{
if (image_to_flip) calibration_src.push_back(image_to_flip);
if (image_to_flip2) calibration_src.push_back(image_to_flip2);
if (m_output_scaling == output_scaling_mode::fsr && avconfig.stereo_mode == stereo_render_mode_options::disabled) // 3D will be implemented later
if (m_output_scaling == output_scaling_mode::fsr && !avconfig.stereo_enabled) // 3D will be implemented later
{
// Run upscaling pass before the rest of the output effects pipeline
// This can be done with all upscalers but we already get bilinear upscaling for free if we just out the filters directly
@ -653,7 +653,7 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info)
vk::get_overlay_pass<vk::video_out_calibration_pass>()->run(
*m_current_command_buffer, areau(aspect_ratio), direct_fbo, calibration_src,
avconfig.gamma, !use_full_rgb_range_output, avconfig.stereo_mode, single_target_pass);
avconfig.gamma, !use_full_rgb_range_output, avconfig.stereo_enabled, g_cfg.video.stereo_render_mode, single_target_pass);
direct_fbo->release();
}

View file

@ -47,35 +47,35 @@ namespace vk
vkDestroyFramebuffer(m_device, value, nullptr);
}
u32 width()
u32 width() const
{
return m_width;
}
u32 height()
u32 height() const
{
return m_height;
}
u8 samples()
u8 samples() const
{
ensure(!attachments.empty());
return attachments[0]->image()->samples();
}
VkFormat format()
VkFormat format() const
{
ensure(!attachments.empty());
return attachments[0]->image()->format();
}
VkFormat depth_format()
VkFormat depth_format() const
{
ensure(!attachments.empty());
return attachments.back()->image()->format();
}
bool matches(const std::vector<vk::image*>& fbo_images, u32 width, u32 height)
bool matches(const std::vector<vk::image*>& fbo_images, u32 width, u32 height) const
{
if (m_width != width || m_height != height)
return false;

View file

@ -189,7 +189,7 @@ namespace rsx
size2u avconf::video_frame_size() const
{
if (state && stereo_mode != stereo_render_mode_options::disabled)
if (state && stereo_enabled)
{
return size2u{ resolution_x, (resolution_y - 30) / 2 };
}

View file

@ -149,16 +149,16 @@ namespace rsx
struct avconf
{
stereo_render_mode_options stereo_mode = stereo_render_mode_options::disabled; // Stereo 3D display mode
u8 format = 0; // XRGB
u8 aspect = 0; // AUTO
u8 resolution_id = 2; // 720p
u32 scanline_pitch = 0; // PACKED
atomic_t<f32> gamma = 1.f; // NO GAMMA CORRECTION
u32 resolution_x = 1280; // X RES
u32 resolution_y = 720; // Y RES
atomic_t<u32> state = 0; // 1 after cellVideoOutConfigure was called
u8 scan_mode = 1; // CELL_VIDEO_OUT_SCAN_MODE_PROGRESSIVE
bool stereo_enabled = false; // Stereo 3D display mode
u8 format = 0; // XRGB
u8 aspect = 0; // AUTO
u8 resolution_id = 2; // 720p
u32 scanline_pitch = 0; // PACKED
atomic_t<f32> gamma = 1.f; // NO GAMMA CORRECTION
u32 resolution_x = 1280; // X RES
u32 resolution_y = 720; // Y RES
atomic_t<u32> state = 0; // 1 after cellVideoOutConfigure was called
u8 scan_mode = 1; // CELL_VIDEO_OUT_SCAN_MODE_PROGRESSIVE
ENABLE_BITWISE_SERIALIZATION;
SAVESTATE_INIT_POS(12);

View file

@ -217,6 +217,7 @@ enum class localized_string_id
HOME_MENU_SETTINGS_VIDEO_OUTPUT_SCALING,
HOME_MENU_SETTINGS_VIDEO_RCAS_SHARPENING,
HOME_MENU_SETTINGS_VIDEO_STRETCH_TO_DISPLAY,
HOME_MENU_SETTINGS_VIDEO_STEREO_MODE,
HOME_MENU_SETTINGS_INPUT,
HOME_MENU_SETTINGS_INPUT_BACKGROUND_INPUT,
HOME_MENU_SETTINGS_INPUT_KEEP_PADS_CONNECTED,

View file

@ -162,7 +162,8 @@ struct cfg_root : cfg::node
cfg::_bool multithreaded_rsx{ this, "Multithreaded RSX", false };
cfg::_bool relaxed_zcull_sync{ this, "Relaxed ZCULL Sync", false };
cfg::_bool force_hw_MSAA_resolve{ this, "Force Hardware MSAA Resolve", false, true };
cfg::_enum<stereo_render_mode_options> stereo_render_mode{ this, "3D Display Mode", stereo_render_mode_options::disabled };
cfg::_bool stereo_enabled{ this, "3D Display Enabled", false };
cfg::_enum<stereo_render_mode_options> stereo_render_mode{ this, "3D Display Mode", stereo_render_mode_options::disabled, true };
cfg::_bool debug_program_analyser{ this, "Debug Program Analyser", false };
cfg::_bool precise_zpass_count{ this, "Accurate ZCULL stats", true };
cfg::_int<1, 8> consecutive_frames_to_draw{ this, "Consecutive Frames To Draw", 1, true};

View file

@ -81,6 +81,7 @@ enum class emu_settings_type
DisableFIFOReordering,
StrictTextureFlushing,
ShaderPrecisionQuality,
StereoRenderEnabled,
StereoRenderMode,
AnisotropicFilterOverride,
TextureLodBias,
@ -284,6 +285,7 @@ inline static const std::map<emu_settings_type, cfg_location> settings_location
{ emu_settings_type::DisableOcclusionQueries, { "Video", "Disable ZCull Occlusion Queries"}},
{ emu_settings_type::DisableVideoOutput, { "Video", "Disable Video Output"}},
{ emu_settings_type::DisableFIFOReordering, { "Video", "Disable FIFO Reordering"}},
{ emu_settings_type::StereoRenderEnabled, { "Video", "3D Display Enabled"}},
{ emu_settings_type::StereoRenderMode, { "Video", "3D Display Mode"}},
{ emu_settings_type::StrictTextureFlushing, { "Video", "Strict Texture Flushing"}},
{ emu_settings_type::ForceCPUBlitEmulation, { "Video", "Force CPU Blit"}},

View file

@ -238,6 +238,7 @@ private:
case localized_string_id::HOME_MENU_SETTINGS_VIDEO_OUTPUT_SCALING: return tr("Output Scaling", "Video");
case localized_string_id::HOME_MENU_SETTINGS_VIDEO_RCAS_SHARPENING: return tr("FidelityFX CAS Sharpening Intensity", "Video");
case localized_string_id::HOME_MENU_SETTINGS_VIDEO_STRETCH_TO_DISPLAY: return tr("Stretch To Display Area", "Video");
case localized_string_id::HOME_MENU_SETTINGS_VIDEO_STEREO_MODE: return tr("Stereo Mode", "Video");
case localized_string_id::HOME_MENU_SETTINGS_INPUT: return tr("Input");
case localized_string_id::HOME_MENU_SETTINGS_INPUT_BACKGROUND_INPUT: return tr("Background Input Enabled", "Input");
case localized_string_id::HOME_MENU_SETTINGS_INPUT_KEEP_PADS_CONNECTED: return tr("Keep Pads Connected", "Input");

View file

@ -640,21 +640,27 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> gui_settings, std
// 3D
m_emu_settings->EnhanceComboBox(ui->stereoRenderMode, emu_settings_type::StereoRenderMode);
m_emu_settings->EnhanceCheckBox(ui->stereoRenderEnabled, emu_settings_type::StereoRenderEnabled);
SubscribeTooltip(ui->gb_stereo, tooltips.settings.stereo_render_mode);
if (game)
{
const auto on_resolution = [this](int index)
const auto enable_3D_modes = [this]()
{
const auto [text, value] = get_data(ui->resBox, index);
ui->stereoRenderMode->setEnabled(value == static_cast<int>(video_resolution::_720p));
const auto [text, value] = get_data(ui->resBox, ui->resBox->currentIndex());
const bool stereo_allowed = value == static_cast<int>(video_resolution::_720p);
const bool stereo_enabled = ui->stereoRenderEnabled->checkState() == Qt::CheckState::Checked;
ui->stereoRenderMode->setEnabled(stereo_allowed && stereo_enabled);
ui->stereoRenderEnabled->setEnabled(stereo_allowed);
};
connect(ui->resBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, on_resolution);
on_resolution(ui->resBox->currentIndex());
connect(ui->resBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [enable_3D_modes](int){ enable_3D_modes(); });
connect(ui->stereoRenderEnabled, &QCheckBox::checkStateChanged, this, [enable_3D_modes](Qt::CheckState){ enable_3D_modes(); });
enable_3D_modes();
}
else
{
ui->stereoRenderMode->setCurrentIndex(find_item(ui->stereoRenderMode, static_cast<int>(g_cfg.video.stereo_render_mode.def)));
ui->stereoRenderMode->setEnabled(false);
ui->stereoRenderEnabled->setChecked(false);
ui->gb_stereo->setEnabled(false);
}
// Checkboxes: main options

View file

@ -551,6 +551,13 @@
<string>3D</string>
</property>
<layout class="QVBoxLayout" name="gb_stereo_layout">
<item>
<widget class="QCheckBox" name="stereoRenderEnabled">
<property name="text">
<string>Enable 3D Support</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="stereoRenderMode"/>
</item>