diff --git a/src/citra/config.cpp b/src/citra/config.cpp index 400c655ff..865f5bc85 100644 --- a/src/citra/config.cpp +++ b/src/citra/config.cpp @@ -110,13 +110,13 @@ void Config::ReadValues() { // Renderer Settings::values.use_gles = sdl2_config->GetBoolean("Renderer", "use_gles", false); Settings::values.use_hw_renderer = sdl2_config->GetBoolean("Renderer", "use_hw_renderer", true); + Settings::values.use_hw_shader = sdl2_config->GetBoolean("Renderer", "use_hw_shader", true); #ifdef __APPLE__ - // Hardware shader is broken on macos thanks to poor drivers. + // Separable shader is broken on macos with Intel GPU thanks to poor drivers. // We still want to provide this option for test/development purposes, but disable it by // default. - Settings::values.use_hw_shader = sdl2_config->GetBoolean("Renderer", "use_hw_shader", false); -#else - Settings::values.use_hw_shader = sdl2_config->GetBoolean("Renderer", "use_hw_shader", true); + Settings::values.separable_shader = + sdl2_config->GetBoolean("Renderer", "separable_shader", false); #endif Settings::values.shaders_accurate_mul = sdl2_config->GetBoolean("Renderer", "shaders_accurate_mul", false); diff --git a/src/citra/default_ini.h b/src/citra/default_ini.h index a6f7d5585..9a60f566e 100644 --- a/src/citra/default_ini.h +++ b/src/citra/default_ini.h @@ -110,6 +110,10 @@ use_hw_renderer = # 0: Software, 1 (default): Hardware use_hw_shader = +# Whether to use separable shaders to emulate 3DS shaders (macOS only) +# 0: Off (Default), 1 : On +separable_shader = + # Whether to use accurate multiplication in hardware shaders # 0: Off (Default. Faster, but causes issues in some games) 1: On (Slower, but correct) shaders_accurate_mul = diff --git a/src/citra_qt/configuration/config.cpp b/src/citra_qt/configuration/config.cpp index 88be0330f..068be17d6 100644 --- a/src/citra_qt/configuration/config.cpp +++ b/src/citra_qt/configuration/config.cpp @@ -431,13 +431,13 @@ void Config::ReadRendererValues() { Settings::values.use_hw_renderer = ReadSetting(QStringLiteral("use_hw_renderer"), true).toBool(); + Settings::values.use_hw_shader = ReadSetting(QStringLiteral("use_hw_shader"), true).toBool(); #ifdef __APPLE__ - // Hardware shader is broken on macos thanks to poor drivers. + // Hardware shader is broken on macos with Intel GPUs thanks to poor drivers. // We still want to provide this option for test/development purposes, but disable it by // default. - Settings::values.use_hw_shader = ReadSetting(QStringLiteral("use_hw_shader"), false).toBool(); -#else - Settings::values.use_hw_shader = ReadSetting(QStringLiteral("use_hw_shader"), true).toBool(); + Settings::values.separable_shader = + ReadSetting(QStringLiteral("separable_shader"), false).toBool(); #endif Settings::values.shaders_accurate_mul = ReadSetting(QStringLiteral("shaders_accurate_mul"), false).toBool(); @@ -916,13 +916,11 @@ void Config::SaveRendererValues() { qt_config->beginGroup(QStringLiteral("Renderer")); WriteSetting(QStringLiteral("use_hw_renderer"), Settings::values.use_hw_renderer, true); + WriteSetting(QStringLiteral("use_hw_shader"), Settings::values.use_hw_shader, true); #ifdef __APPLE__ // Hardware shader is broken on macos thanks to poor drivers. - // We still want to provide this option for test/development purposes, but disable it by - // default. - WriteSetting(QStringLiteral("use_hw_shader"), Settings::values.use_hw_shader, false); -#else - WriteSetting(QStringLiteral("use_hw_shader"), Settings::values.use_hw_shader, true); + // TODO: enable this for none Intel GPUs + WriteSetting(QStringLiteral("use_separable_shader"), Settings::values.separable_shader, false); #endif WriteSetting(QStringLiteral("shaders_accurate_mul"), Settings::values.shaders_accurate_mul, false); diff --git a/src/citra_qt/configuration/configure_graphics.cpp b/src/citra_qt/configuration/configure_graphics.cpp index b9dd4b468..66c3f6e8b 100644 --- a/src/citra_qt/configuration/configure_graphics.cpp +++ b/src/citra_qt/configuration/configure_graphics.cpp @@ -29,15 +29,24 @@ ConfigureGraphics::ConfigureGraphics(QWidget* parent) connect(ui->toggle_hw_shader, &QCheckBox::toggled, ui->hw_shader_group, &QWidget::setEnabled); #ifdef __APPLE__ connect(ui->toggle_hw_shader, &QCheckBox::stateChanged, this, [this](int state) { + if (state == Qt::Checked) { + ui->toggle_separable_shader->setEnabled(true); + } + }); + connect(ui->toggle_separable_shader, &QCheckBox::stateChanged, this, [this](int state) { if (state == Qt::Checked) { QMessageBox::warning( this, tr("Hardware Shader Warning"), - tr("Hardware Shader support is broken on macOS, and will cause graphical issues " + tr("Separable Shader support is broken on macOS with Intel GPUs, and will cause " + "graphical issues " "like showing a black screen.

The option is only there for " "test/development purposes. If you experience graphical issues with Hardware " "Shader, please turn it off.")); } }); +#else + // TODO(B3N30): Hide this for macs with none Intel GPUs, too. + ui->toggle_separable_shader->setVisible(false); #endif } @@ -46,6 +55,7 @@ ConfigureGraphics::~ConfigureGraphics() = default; void ConfigureGraphics::SetConfiguration() { ui->toggle_hw_renderer->setChecked(Settings::values.use_hw_renderer); ui->toggle_hw_shader->setChecked(Settings::values.use_hw_shader); + ui->toggle_separable_shader->setChecked(Settings::values.separable_shader); ui->toggle_accurate_mul->setChecked(Settings::values.shaders_accurate_mul); ui->toggle_shader_jit->setChecked(Settings::values.use_shader_jit); ui->toggle_vsync_new->setChecked(Settings::values.use_vsync_new); @@ -54,6 +64,7 @@ void ConfigureGraphics::SetConfiguration() { void ConfigureGraphics::ApplyConfiguration() { Settings::values.use_hw_renderer = ui->toggle_hw_renderer->isChecked(); Settings::values.use_hw_shader = ui->toggle_hw_shader->isChecked(); + Settings::values.separable_shader = ui->toggle_separable_shader->isChecked(); Settings::values.shaders_accurate_mul = ui->toggle_accurate_mul->isChecked(); Settings::values.use_shader_jit = ui->toggle_shader_jit->isChecked(); Settings::values.use_vsync_new = ui->toggle_vsync_new->isChecked(); diff --git a/src/citra_qt/configuration/configure_graphics.ui b/src/citra_qt/configuration/configure_graphics.ui index 43f538558..f3d169427 100644 --- a/src/citra_qt/configuration/configure_graphics.ui +++ b/src/citra_qt/configuration/configure_graphics.ui @@ -76,6 +76,13 @@ 0 + + + + Separable Shader (Intel GPUs only) + + + diff --git a/src/core/settings.cpp b/src/core/settings.cpp index 6af80205b..22bec6faf 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -27,6 +27,7 @@ void Apply() { VideoCore::g_hw_renderer_enabled = values.use_hw_renderer; VideoCore::g_shader_jit_enabled = values.use_shader_jit; VideoCore::g_hw_shader_enabled = values.use_hw_shader; + VideoCore::g_separable_shader_enabled = values.separable_shader; VideoCore::g_hw_shader_accurate_mul = values.shaders_accurate_mul; VideoCore::g_use_disk_shader_cache = values.use_disk_shader_cache; @@ -78,6 +79,7 @@ void LogSettings() { LogSetting("Renderer_UseGLES", Settings::values.use_gles); LogSetting("Renderer_UseHwRenderer", Settings::values.use_hw_renderer); LogSetting("Renderer_UseHwShader", Settings::values.use_hw_shader); + LogSetting("Renderer_SeparableShader", Settings::values.separable_shader); LogSetting("Renderer_ShadersAccurateMul", Settings::values.shaders_accurate_mul); LogSetting("Renderer_UseShaderJit", Settings::values.use_shader_jit); LogSetting("Renderer_UseResolutionFactor", Settings::values.resolution_factor); diff --git a/src/core/settings.h b/src/core/settings.h index 70bdd8c4c..db7a20359 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -142,6 +142,7 @@ struct Values { bool use_gles; bool use_hw_renderer; bool use_hw_shader; + bool separable_shader; bool use_disk_shader_cache; bool shaders_accurate_mul; bool use_shader_jit; diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 3a0acc425..0b826fd90 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -43,6 +43,10 @@ static bool IsVendorAmd() { const std::string_view gpu_vendor{reinterpret_cast(glGetString(GL_VENDOR))}; return gpu_vendor == "ATI Technologies Inc." || gpu_vendor == "Advanced Micro Devices, Inc."; } +static bool IsVendorIntel() { + std::string gpu_vendor{reinterpret_cast(glGetString(GL_VENDOR))}; + return gpu_vendor == "Intel Inc."; +} RasterizerOpenGL::RasterizerOpenGL() : is_amd(IsVendorAmd()), vertex_buffer(GL_ARRAY_BUFFER, VERTEX_BUFFER_SIZE, is_amd), @@ -160,8 +164,19 @@ RasterizerOpenGL::RasterizerOpenGL() state.Apply(); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer.GetHandle()); +#ifdef __APPLE__ + if (IsVendorIntel()) { + shader_program_manager = std::make_unique( + VideoCore::g_separable_shader_enabled ? GLAD_GL_ARB_separate_shader_objects : false, + is_amd); + } else { + shader_program_manager = + std::make_unique(GLAD_GL_ARB_separate_shader_objects, is_amd); + } +#else shader_program_manager = std::make_unique(GLAD_GL_ARB_separate_shader_objects, is_amd); +#endif glEnable(GL_BLEND); diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp index 619ea3d4c..87310c5ce 100644 --- a/src/video_core/video_core.cpp +++ b/src/video_core/video_core.cpp @@ -23,6 +23,7 @@ std::unique_ptr g_renderer; ///< Renderer plugin std::atomic g_hw_renderer_enabled; std::atomic g_shader_jit_enabled; std::atomic g_hw_shader_enabled; +std::atomic g_separable_shader_enabled; std::atomic g_hw_shader_accurate_mul; std::atomic g_use_disk_shader_cache; std::atomic g_renderer_bg_color_update_requested; diff --git a/src/video_core/video_core.h b/src/video_core/video_core.h index 409f4deb2..9e12cfda6 100644 --- a/src/video_core/video_core.h +++ b/src/video_core/video_core.h @@ -31,6 +31,7 @@ extern std::unique_ptr g_renderer; ///< Renderer plugin extern std::atomic g_hw_renderer_enabled; extern std::atomic g_shader_jit_enabled; extern std::atomic g_hw_shader_enabled; +extern std::atomic g_separable_shader_enabled; extern std::atomic g_hw_shader_accurate_mul; extern std::atomic g_use_disk_shader_cache; extern std::atomic g_renderer_bg_color_update_requested;