From c63f0f37cd84d627dd40ace3205c689efc068ac0 Mon Sep 17 00:00:00 2001 From: Pokechu22 Date: Sat, 25 Mar 2023 17:16:53 -0700 Subject: [PATCH 1/3] VideoCommon: Pass WindowSystemInfo to InitBackendInfo --- Source/Core/Core/Core.cpp | 4 +- .../Config/Graphics/GraphicsWindow.cpp | 4 +- .../Config/Graphics/GraphicsWindow.h | 2 + Source/Core/DolphinQt/MainWindow.cpp | 11 ++- Source/Core/DolphinQt/MainWindow.h | 2 + Source/Core/VideoBackends/D3D/D3DMain.cpp | 2 +- Source/Core/VideoBackends/D3D/VideoBackend.h | 2 +- .../Core/VideoBackends/D3D12/VideoBackend.cpp | 2 +- .../Core/VideoBackends/D3D12/VideoBackend.h | 2 +- Source/Core/VideoBackends/Metal/MTLMain.mm | 2 +- .../Core/VideoBackends/Metal/VideoBackend.h | 2 +- .../Core/VideoBackends/Null/NullBackend.cpp | 2 +- Source/Core/VideoBackends/Null/VideoBackend.h | 2 +- Source/Core/VideoBackends/OGL/OGLMain.cpp | 68 +++++++++++-------- Source/Core/VideoBackends/OGL/VideoBackend.h | 4 +- Source/Core/VideoBackends/Software/SWmain.cpp | 2 +- .../VideoBackends/Software/VideoBackend.h | 2 +- Source/Core/VideoBackends/Vulkan/VKMain.cpp | 2 +- .../Core/VideoBackends/Vulkan/VideoBackend.h | 2 +- Source/Core/VideoCommon/VideoBackendBase.cpp | 8 +-- Source/Core/VideoCommon/VideoBackendBase.h | 6 +- 21 files changed, 76 insertions(+), 57 deletions(-) diff --git a/Source/Core/Core/Core.cpp b/Source/Core/Core/Core.cpp index fb97379411..dbcca8a687 100644 --- a/Source/Core/Core/Core.cpp +++ b/Source/Core/Core/Core.cpp @@ -261,7 +261,7 @@ bool Init(std::unique_ptr boot, const WindowSystemInfo& wsi) Host_UpdateMainFrame(); // Disable any menus or buttons at boot // Manually reactivate the video backend in case a GameINI overrides the video backend setting. - VideoBackendBase::PopulateBackendInfo(); + VideoBackendBase::PopulateBackendInfo(wsi); // Issue any API calls which must occur on the main thread for the graphics backend. WindowSystemInfo prepared_wsi(wsi); @@ -579,7 +579,7 @@ static void EmuThread(std::unique_ptr boot, WindowSystemInfo wsi system.GetPowerPC().GetDebugInterface().Clear(guard); }}; - VideoBackendBase::PopulateBackendInfo(); + VideoBackendBase::PopulateBackendInfo(wsi); if (!g_video_backend->Initialize(wsi)) { diff --git a/Source/Core/DolphinQt/Config/Graphics/GraphicsWindow.cpp b/Source/Core/DolphinQt/Config/Graphics/GraphicsWindow.cpp index 535458685c..7b31cc7f6e 100644 --- a/Source/Core/DolphinQt/Config/Graphics/GraphicsWindow.cpp +++ b/Source/Core/DolphinQt/Config/Graphics/GraphicsWindow.cpp @@ -24,7 +24,7 @@ #include "VideoCommon/VideoBackendBase.h" #include "VideoCommon/VideoConfig.h" -GraphicsWindow::GraphicsWindow(MainWindow* parent) : QDialog(parent) +GraphicsWindow::GraphicsWindow(MainWindow* parent) : QDialog(parent), m_main_window(parent) { CreateMainLayout(); @@ -68,7 +68,7 @@ void GraphicsWindow::CreateMainLayout() void GraphicsWindow::OnBackendChanged(const QString& backend_name) { Config::SetBase(Config::MAIN_GFX_BACKEND, backend_name.toStdString()); - VideoBackendBase::PopulateBackendInfoFromUI(); + VideoBackendBase::PopulateBackendInfoFromUI(m_main_window->GetWindowSystemInfo()); setWindowTitle( tr("%1 Graphics Configuration").arg(tr(g_video_backend->GetDisplayName().c_str()))); diff --git a/Source/Core/DolphinQt/Config/Graphics/GraphicsWindow.h b/Source/Core/DolphinQt/Config/Graphics/GraphicsWindow.h index c345de3fef..5949a2dda3 100644 --- a/Source/Core/DolphinQt/Config/Graphics/GraphicsWindow.h +++ b/Source/Core/DolphinQt/Config/Graphics/GraphicsWindow.h @@ -28,4 +28,6 @@ signals: private: void CreateMainLayout(); void OnBackendChanged(const QString& backend); + + MainWindow* const m_main_window; }; diff --git a/Source/Core/DolphinQt/MainWindow.cpp b/Source/Core/DolphinQt/MainWindow.cpp index 8262c8f01e..42a6a04603 100644 --- a/Source/Core/DolphinQt/MainWindow.cpp +++ b/Source/Core/DolphinQt/MainWindow.cpp @@ -343,12 +343,17 @@ MainWindow::~MainWindow() Config::Save(); } +WindowSystemInfo MainWindow::GetWindowSystemInfo() const +{ + return ::GetWindowSystemInfo(m_render_widget->windowHandle()); +} + void MainWindow::InitControllers() { if (g_controller_interface.IsInit()) return; - UICommon::InitControllers(GetWindowSystemInfo(windowHandle())); + UICommon::InitControllers(::GetWindowSystemInfo(windowHandle())); m_hotkey_scheduler = new HotkeyScheduler(); m_hotkey_scheduler->Start(); @@ -1098,7 +1103,7 @@ void MainWindow::StartGame(std::unique_ptr&& parameters) // Boot up, show an error if it fails to load the game. if (!BootManager::BootCore(std::move(parameters), - GetWindowSystemInfo(m_render_widget->windowHandle()))) + ::GetWindowSystemInfo(m_render_widget->windowHandle()))) { ModalMessageBox::critical(this, tr("Error"), tr("Failed to init core"), QMessageBox::Ok); HideRenderWidget(); @@ -1206,7 +1211,7 @@ void MainWindow::HideRenderWidget(bool reinit, bool is_exit) // The controller interface will still be registered to the old render widget, if the core // has booted. Therefore, we should re-bind it to the main window for now. When the core // is next started, it will be swapped back to the new render widget. - g_controller_interface.ChangeWindow(GetWindowSystemInfo(windowHandle()).render_window, + g_controller_interface.ChangeWindow(::GetWindowSystemInfo(windowHandle()).render_window, is_exit ? ControllerInterface::WindowChangeReason::Exit : ControllerInterface::WindowChangeReason::Other); } diff --git a/Source/Core/DolphinQt/MainWindow.h b/Source/Core/DolphinQt/MainWindow.h index fa3a274bfc..4654202ed7 100644 --- a/Source/Core/DolphinQt/MainWindow.h +++ b/Source/Core/DolphinQt/MainWindow.h @@ -50,6 +50,7 @@ class ThreadWidget; class ToolBar; class WatchWidget; class WiiTASInputWindow; +struct WindowSystemInfo; namespace DiscIO { @@ -76,6 +77,7 @@ public: ~MainWindow(); void Show(); + WindowSystemInfo GetWindowSystemInfo() const; bool eventFilter(QObject* object, QEvent* event) override; diff --git a/Source/Core/VideoBackends/D3D/D3DMain.cpp b/Source/Core/VideoBackends/D3D/D3DMain.cpp index 8256674ad5..4f797fcb26 100644 --- a/Source/Core/VideoBackends/D3D/D3DMain.cpp +++ b/Source/Core/VideoBackends/D3D/D3DMain.cpp @@ -63,7 +63,7 @@ std::optional VideoBackend::GetWarningMessage() const return result; } -void VideoBackend::InitBackendInfo() +void VideoBackend::InitBackendInfo(const WindowSystemInfo& wsi) { if (!D3DCommon::LoadLibraries()) return; diff --git a/Source/Core/VideoBackends/D3D/VideoBackend.h b/Source/Core/VideoBackends/D3D/VideoBackend.h index 1349d13b2b..6a94f8c7a3 100644 --- a/Source/Core/VideoBackends/D3D/VideoBackend.h +++ b/Source/Core/VideoBackends/D3D/VideoBackend.h @@ -18,7 +18,7 @@ public: std::string GetDisplayName() const override; std::optional GetWarningMessage() const override; - void InitBackendInfo() override; + void InitBackendInfo(const WindowSystemInfo& wsi) override; static constexpr const char* NAME = "D3D"; diff --git a/Source/Core/VideoBackends/D3D12/VideoBackend.cpp b/Source/Core/VideoBackends/D3D12/VideoBackend.cpp index afc5bb96e8..f82b7d961b 100644 --- a/Source/Core/VideoBackends/D3D12/VideoBackend.cpp +++ b/Source/Core/VideoBackends/D3D12/VideoBackend.cpp @@ -36,7 +36,7 @@ std::string VideoBackend::GetDisplayName() const return "Direct3D 12"; } -void VideoBackend::InitBackendInfo() +void VideoBackend::InitBackendInfo(const WindowSystemInfo& wsi) { if (!D3DCommon::LoadLibraries()) return; diff --git a/Source/Core/VideoBackends/D3D12/VideoBackend.h b/Source/Core/VideoBackends/D3D12/VideoBackend.h index 7d3126b38c..db03b738d0 100644 --- a/Source/Core/VideoBackends/D3D12/VideoBackend.h +++ b/Source/Core/VideoBackends/D3D12/VideoBackend.h @@ -16,7 +16,7 @@ public: std::string GetName() const override; std::string GetDisplayName() const override; - void InitBackendInfo() override; + void InitBackendInfo(const WindowSystemInfo& wsi) override; static constexpr const char* NAME = "D3D12"; diff --git a/Source/Core/VideoBackends/Metal/MTLMain.mm b/Source/Core/VideoBackends/Metal/MTLMain.mm index f799d5eea1..7042e091fd 100644 --- a/Source/Core/VideoBackends/Metal/MTLMain.mm +++ b/Source/Core/VideoBackends/Metal/MTLMain.mm @@ -119,7 +119,7 @@ void Metal::VideoBackend::Shutdown() ObjectCache::Shutdown(); } -void Metal::VideoBackend::InitBackendInfo() +void Metal::VideoBackend::InitBackendInfo(const WindowSystemInfo& wsi) { @autoreleasepool { diff --git a/Source/Core/VideoBackends/Metal/VideoBackend.h b/Source/Core/VideoBackends/Metal/VideoBackend.h index 3a567718e2..a6a24173e5 100644 --- a/Source/Core/VideoBackends/Metal/VideoBackend.h +++ b/Source/Core/VideoBackends/Metal/VideoBackend.h @@ -18,7 +18,7 @@ public: std::string GetDisplayName() const override; std::optional GetWarningMessage() const override; - void InitBackendInfo() override; + void InitBackendInfo(const WindowSystemInfo& wsi) override; void PrepareWindow(WindowSystemInfo& wsi) override; diff --git a/Source/Core/VideoBackends/Null/NullBackend.cpp b/Source/Core/VideoBackends/Null/NullBackend.cpp index 900a911699..28afcce4dc 100644 --- a/Source/Core/VideoBackends/Null/NullBackend.cpp +++ b/Source/Core/VideoBackends/Null/NullBackend.cpp @@ -25,7 +25,7 @@ namespace Null { -void VideoBackend::InitBackendInfo() +void VideoBackend::InitBackendInfo(const WindowSystemInfo& wsi) { g_Config.backend_info.api_type = APIType::Nothing; g_Config.backend_info.MaxTextureSize = 16384; diff --git a/Source/Core/VideoBackends/Null/VideoBackend.h b/Source/Core/VideoBackends/Null/VideoBackend.h index f08098cfd0..4437c0c48d 100644 --- a/Source/Core/VideoBackends/Null/VideoBackend.h +++ b/Source/Core/VideoBackends/Null/VideoBackend.h @@ -15,7 +15,7 @@ public: std::string GetName() const override { return NAME; } std::string GetDisplayName() const override; - void InitBackendInfo() override; + void InitBackendInfo(const WindowSystemInfo& wsi) override; static constexpr const char* NAME = "Null"; }; diff --git a/Source/Core/VideoBackends/OGL/OGLMain.cpp b/Source/Core/VideoBackends/OGL/OGLMain.cpp index c47b94ceb8..ef25e40a2a 100644 --- a/Source/Core/VideoBackends/OGL/OGLMain.cpp +++ b/Source/Core/VideoBackends/OGL/OGLMain.cpp @@ -74,8 +74,45 @@ std::string VideoBackend::GetDisplayName() const return _trans("OpenGL"); } -void VideoBackend::InitBackendInfo() +void VideoBackend::InitBackendInfo(const WindowSystemInfo& wsi) { + std::unique_ptr temp_gl_context = + GLContext::Create(wsi, g_Config.stereo_mode == StereoMode::QuadBuffer, true, false, + Config::Get(Config::GFX_PREFER_GLES)); + + if (!temp_gl_context) + return; + + FillBackendInfo(temp_gl_context.get()); +} + +bool VideoBackend::InitializeGLExtensions(GLContext* context) +{ + // Init extension support. + if (!GLExtensions::Init(context)) + { + // OpenGL 2.0 is required for all shader based drawings. There is no way to get this by + // extensions + PanicAlertFmtT("GPU: OGL ERROR: Does your video card support OpenGL 2.0?"); + return false; + } + + if (GLExtensions::Version() < 300) + { + // integer vertex attributes require a gl3 only function + PanicAlertFmtT("GPU: OGL ERROR: Need OpenGL version 3.\n" + "GPU: Does your video card support OpenGL 3?"); + return false; + } + + return true; +} + +bool VideoBackend::FillBackendInfo(GLContext* context) +{ + if (!InitializeGLExtensions(context)) + return false; + g_Config.backend_info.api_type = APIType::OpenGL; g_Config.backend_info.MaxTextureSize = 16384; g_Config.backend_info.bUsesLowerLeftOrigin = true; @@ -123,33 +160,6 @@ void VideoBackend::InitBackendInfo() // aamodes - 1 is to stay consistent with D3D (means no AA) g_Config.backend_info.AAModes = {1, 2, 4, 8}; -} - -bool VideoBackend::InitializeGLExtensions(GLContext* context) -{ - // Init extension support. - if (!GLExtensions::Init(context)) - { - // OpenGL 2.0 is required for all shader based drawings. There is no way to get this by - // extensions - PanicAlertFmtT("GPU: OGL ERROR: Does your video card support OpenGL 2.0?"); - return false; - } - - if (GLExtensions::Version() < 300) - { - // integer vertex attributes require a gl3 only function - PanicAlertFmtT("GPU: OGL ERROR: Need OpenGL version 3.\n" - "GPU: Does your video card support OpenGL 3?"); - return false; - } - - return true; -} - -bool VideoBackend::FillBackendInfo() -{ - InitBackendInfo(); // check for the max vertex attributes GLint numvertexattribs = 0; @@ -184,7 +194,7 @@ bool VideoBackend::Initialize(const WindowSystemInfo& wsi) if (!main_gl_context) return false; - if (!InitializeGLExtensions(main_gl_context.get()) || !FillBackendInfo()) + if (!FillBackendInfo(main_gl_context.get())) return false; auto gfx = std::make_unique(std::move(main_gl_context), wsi.render_surface_scale); diff --git a/Source/Core/VideoBackends/OGL/VideoBackend.h b/Source/Core/VideoBackends/OGL/VideoBackend.h index 4be861954e..53f7f940d5 100644 --- a/Source/Core/VideoBackends/OGL/VideoBackend.h +++ b/Source/Core/VideoBackends/OGL/VideoBackend.h @@ -19,12 +19,12 @@ public: std::string GetName() const override; std::string GetDisplayName() const override; - void InitBackendInfo() override; + void InitBackendInfo(const WindowSystemInfo& wsi) override; static constexpr const char* NAME = "OGL"; private: bool InitializeGLExtensions(GLContext* context); - bool FillBackendInfo(); + bool FillBackendInfo(GLContext* context); }; } // namespace OGL diff --git a/Source/Core/VideoBackends/Software/SWmain.cpp b/Source/Core/VideoBackends/Software/SWmain.cpp index 8703ea4b4d..ccb040e8ad 100644 --- a/Source/Core/VideoBackends/Software/SWmain.cpp +++ b/Source/Core/VideoBackends/Software/SWmain.cpp @@ -62,7 +62,7 @@ std::optional VideoSoftware::GetWarningMessage() const "really want to enable software rendering? If unsure, select 'No'."); } -void VideoSoftware::InitBackendInfo() +void VideoSoftware::InitBackendInfo(const WindowSystemInfo& wsi) { g_Config.backend_info.api_type = APIType::Nothing; g_Config.backend_info.MaxTextureSize = 16384; diff --git a/Source/Core/VideoBackends/Software/VideoBackend.h b/Source/Core/VideoBackends/Software/VideoBackend.h index 8c3cb081ef..35c3adb1a7 100644 --- a/Source/Core/VideoBackends/Software/VideoBackend.h +++ b/Source/Core/VideoBackends/Software/VideoBackend.h @@ -17,7 +17,7 @@ class VideoSoftware : public VideoBackendBase std::string GetDisplayName() const override; std::optional GetWarningMessage() const override; - void InitBackendInfo() override; + void InitBackendInfo(const WindowSystemInfo& wsi) override; static constexpr const char* NAME = "Software Renderer"; }; diff --git a/Source/Core/VideoBackends/Vulkan/VKMain.cpp b/Source/Core/VideoBackends/Vulkan/VKMain.cpp index 053b592c14..2eb9b34106 100644 --- a/Source/Core/VideoBackends/Vulkan/VKMain.cpp +++ b/Source/Core/VideoBackends/Vulkan/VKMain.cpp @@ -30,7 +30,7 @@ namespace Vulkan { -void VideoBackend::InitBackendInfo() +void VideoBackend::InitBackendInfo(const WindowSystemInfo& wsi) { VulkanContext::PopulateBackendInfo(&g_Config); diff --git a/Source/Core/VideoBackends/Vulkan/VideoBackend.h b/Source/Core/VideoBackends/Vulkan/VideoBackend.h index a16d149307..4e8c3a5471 100644 --- a/Source/Core/VideoBackends/Vulkan/VideoBackend.h +++ b/Source/Core/VideoBackends/Vulkan/VideoBackend.h @@ -16,7 +16,7 @@ public: std::string GetName() const override { return NAME; } std::string GetDisplayName() const override { return _trans("Vulkan"); } - void InitBackendInfo() override; + void InitBackendInfo(const WindowSystemInfo& wsi) override; void PrepareWindow(WindowSystemInfo& wsi) override; static constexpr const char* NAME = "Vulkan"; diff --git a/Source/Core/VideoCommon/VideoBackendBase.cpp b/Source/Core/VideoCommon/VideoBackendBase.cpp index 9d6ff70664..6e466c8557 100644 --- a/Source/Core/VideoCommon/VideoBackendBase.cpp +++ b/Source/Core/VideoCommon/VideoBackendBase.cpp @@ -281,7 +281,7 @@ void VideoBackendBase::ActivateBackend(const std::string& name) g_video_backend = iter->get(); } -void VideoBackendBase::PopulateBackendInfo() +void VideoBackendBase::PopulateBackendInfo(const WindowSystemInfo& wsi) { g_Config.Refresh(); // Reset backend_info so if the backend forgets to initialize something it doesn't end up using @@ -289,18 +289,18 @@ void VideoBackendBase::PopulateBackendInfo() g_Config.backend_info = {}; ActivateBackend(Config::Get(Config::MAIN_GFX_BACKEND)); g_Config.backend_info.DisplayName = g_video_backend->GetDisplayName(); - g_video_backend->InitBackendInfo(); + g_video_backend->InitBackendInfo(wsi); // We validate the config after initializing the backend info, as system-specific settings // such as anti-aliasing, or the selected adapter may be invalid, and should be checked. g_Config.VerifyValidity(); } -void VideoBackendBase::PopulateBackendInfoFromUI() +void VideoBackendBase::PopulateBackendInfoFromUI(const WindowSystemInfo& wsi) { // If the core is running, the backend info will have been populated already. // If we did it here, the UI thread can race with the with the GPU thread. if (!Core::IsRunning()) - PopulateBackendInfo(); + PopulateBackendInfo(wsi); } void VideoBackendBase::DoState(PointerWrap& p) diff --git a/Source/Core/VideoCommon/VideoBackendBase.h b/Source/Core/VideoCommon/VideoBackendBase.h index 2ce235f8f8..f5222a1936 100644 --- a/Source/Core/VideoCommon/VideoBackendBase.h +++ b/Source/Core/VideoCommon/VideoBackendBase.h @@ -47,7 +47,7 @@ public: virtual std::string GetName() const = 0; virtual std::string GetDisplayName() const { return GetName(); } - virtual void InitBackendInfo() = 0; + virtual void InitBackendInfo(const WindowSystemInfo& wsi) = 0; virtual std::optional GetWarningMessage() const { return {}; } // Prepares a native window for rendering. This is called on the main thread, or the @@ -69,9 +69,9 @@ public: static void ActivateBackend(const std::string& name); // Fills the backend_info fields with the capabilities of the selected backend/device. - static void PopulateBackendInfo(); + static void PopulateBackendInfo(const WindowSystemInfo& wsi); // Called by the UI thread when the graphics config is opened. - static void PopulateBackendInfoFromUI(); + static void PopulateBackendInfoFromUI(const WindowSystemInfo& wsi); // Wrapper function which pushes the event to the GPU thread. void DoState(PointerWrap& p); From b246a634d42bc50d5b3ba1c97891e195c37293fe Mon Sep 17 00:00:00 2001 From: Pokechu22 Date: Sun, 19 Mar 2023 22:20:34 -0700 Subject: [PATCH 2/3] OpenGL: Check the list of supported AA modes instead of hardcoding --- .../Common/GL/GLExtensions/GLExtensions.cpp | 2 +- Source/Core/VideoBackends/OGL/OGLConfig.cpp | 127 +++++++++++++++++- Source/Core/VideoBackends/OGL/OGLConfig.h | 2 - Source/Core/VideoBackends/OGL/OGLGfx.cpp | 6 - Source/Core/VideoBackends/OGL/OGLMain.cpp | 9 +- Source/Core/VideoBackends/OGL/OGLTexture.cpp | 6 +- Source/Core/VideoBackends/OGL/OGLTexture.h | 1 + 7 files changed, 133 insertions(+), 20 deletions(-) diff --git a/Source/Core/Common/GL/GLExtensions/GLExtensions.cpp b/Source/Core/Common/GL/GLExtensions/GLExtensions.cpp index d43e898ca5..e761f9e05a 100644 --- a/Source/Core/Common/GL/GLExtensions/GLExtensions.cpp +++ b/Source/Core/Common/GL/GLExtensions/GLExtensions.cpp @@ -1674,7 +1674,7 @@ const GLFunc gl_function_array[] = { GLFUNC_REQUIRES(glDrawArraysInstancedBaseInstance, "VERSION_4_2"), GLFUNC_REQUIRES(glDrawElementsInstancedBaseInstance, "VERSION_4_2"), GLFUNC_REQUIRES(glDrawElementsInstancedBaseVertexBaseInstance, "VERSION_4_2"), - GLFUNC_REQUIRES(glGetInternalformativ, "VERSION_4_2"), + GLFUNC_REQUIRES(glGetInternalformativ, "VERSION_4_2 |VERSION_GLES_3"), GLFUNC_REQUIRES(glGetActiveAtomicCounterBufferiv, "VERSION_4_2"), GLFUNC_REQUIRES(glBindImageTexture, "VERSION_4_2"), GLFUNC_REQUIRES(glMemoryBarrier, "VERSION_4_2"), diff --git a/Source/Core/VideoBackends/OGL/OGLConfig.cpp b/Source/Core/VideoBackends/OGL/OGLConfig.cpp index e5e1bff83f..aefff7de82 100644 --- a/Source/Core/VideoBackends/OGL/OGLConfig.cpp +++ b/Source/Core/VideoBackends/OGL/OGLConfig.cpp @@ -3,6 +3,11 @@ #include "VideoBackends/OGL/OGLConfig.h" +#include +#include +#include + +#include "Common/Assert.h" #include "Common/GL/GLContext.h" #include "Common/GL/GLExtensions/GLExtensions.h" #include "Common/Logging/LogManager.h" @@ -10,14 +15,13 @@ #include "Core/Config/GraphicsSettings.h" +#include "VideoBackends/OGL/OGLTexture.h" + #include "VideoCommon/DriverDetails.h" +#include "VideoCommon/FramebufferManager.h" #include "VideoCommon/OnScreenDisplay.h" #include "VideoCommon/VideoConfig.h" -#include -#include -#include - namespace OGL { void InitDriverInfo() @@ -534,9 +538,118 @@ bool PopulateConfig(GLContext* m_main_gl_context) g_Config.backend_info.bSupportsEarlyZ = g_ogl_config.bSupportsImageLoadStore || g_ogl_config.bSupportsConservativeDepth; - glGetIntegerv(GL_MAX_SAMPLES, &g_ogl_config.max_samples); - if (g_ogl_config.max_samples < 1 || !g_ogl_config.bSupportsMSAA) - g_ogl_config.max_samples = 1; + g_Config.backend_info.AAModes.clear(); + if (g_ogl_config.bSupportsMSAA) + { + bool supportsGetInternalFormat = + GLExtensions::Supports("VERSION_4_2") || GLExtensions::Supports("VERSION_GLES_3"); + if (supportsGetInternalFormat) + { + // Note: GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES should technically be used for + // GL_OES_texture_storage_multisample_2d_array, but both are 0x9102 so it does not matter. + + std::vector color_aa_modes; + { + GLenum colorInternalFormat = OGLTexture::GetGLInternalFormatForTextureFormat( + FramebufferManager::GetEFBColorFormat(), true); + GLint num_color_sample_counts = 0; + glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, colorInternalFormat, + GL_NUM_SAMPLE_COUNTS, 1, &num_color_sample_counts); + + ASSERT_MSG(VIDEO, num_color_sample_counts >= 0, + "negative GL_NUM_SAMPLE_COUNTS for colors does not make sense: {}", + num_color_sample_counts); + color_aa_modes.reserve(num_color_sample_counts + 1); + if (num_color_sample_counts > 0) + { + color_aa_modes.resize(num_color_sample_counts); + + static_assert(sizeof(GLint) == sizeof(u32)); + glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, colorInternalFormat, GL_SAMPLES, + num_color_sample_counts, + reinterpret_cast(color_aa_modes.data())); + ASSERT_MSG(VIDEO, std::is_sorted(color_aa_modes.rbegin(), color_aa_modes.rend()), + "GPU driver didn't return sorted color AA modes: [{}]", + fmt::join(color_aa_modes, ", ")); + } + + if (color_aa_modes.empty() || color_aa_modes.back() != 1) + color_aa_modes.push_back(1); + } + + std::vector depth_aa_modes; + { + GLenum depthInternalFormat = OGLTexture::GetGLInternalFormatForTextureFormat( + FramebufferManager::GetEFBColorFormat(), true); + GLint num_depth_sample_counts = 0; + glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, depthInternalFormat, + GL_NUM_SAMPLE_COUNTS, 1, &num_depth_sample_counts); + + ASSERT_MSG(VIDEO, num_depth_sample_counts >= 0, + "negative GL_NUM_SAMPLE_COUNTS for depth does not make sense: {}", + num_depth_sample_counts); + depth_aa_modes.reserve(num_depth_sample_counts + 1); + if (num_depth_sample_counts > 0) + { + depth_aa_modes.resize(num_depth_sample_counts); + + static_assert(sizeof(GLint) == sizeof(u32)); + glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, depthInternalFormat, GL_SAMPLES, + num_depth_sample_counts, + reinterpret_cast(depth_aa_modes.data())); + ASSERT_MSG(VIDEO, std::is_sorted(depth_aa_modes.rbegin(), depth_aa_modes.rend()), + "GPU driver didn't return sorted depth AA modes: [{}]", + fmt::join(depth_aa_modes, ", ")); + } + + if (depth_aa_modes.empty() || depth_aa_modes.back() != 1) + depth_aa_modes.push_back(1); + } + + // The spec says supported sample formats are returned in descending numeric order. + // It also says "Only positive values are returned", but does not specify whether 1 is + // included or not; it seems like NVIDIA and Intel GPUs do not include it. + // We've inserted 1 at the back of both if not present to handle this. + g_Config.backend_info.AAModes.clear(); + g_Config.backend_info.AAModes.reserve(std::min(color_aa_modes.size(), depth_aa_modes.size())); + // We only want AA modes that are supported for both the color and depth textures. Probably + // the support is the same, though. rbegin/rend are used to swap the order ahead of time. + std::set_intersection(color_aa_modes.rbegin(), color_aa_modes.rend(), depth_aa_modes.rbegin(), + depth_aa_modes.rend(), + std::back_inserter(g_Config.backend_info.AAModes)); + } + else + { + // The documentation for glGetInternalformativ says its value is at least the minimum of + // GL_MAX_SAMPLES, GL_MAX_COLOR_TEXTURE_SAMPLES, and GL_MAX_DEPTH_TEXTURE_SAMPLES (and + // GL_MAX_INTEGER_SAMPLES for integer textures, assumed not applicable here). + GLint max_color_samples = 0; + glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &max_color_samples); + GLint max_depth_samples = 0; + glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &max_depth_samples); + // Note: The desktop OpenGL ref pages don't actually say that GL_MAX_SAMPLES is a valid + // parameter for glGetIntegerv (though the ES ones do). However, MAX_SAMPLES is + // referenced in the GL 3.1 spec and by GL_ARB_texture_multisample (which is written against + // the OpenGL 3.1 spec), so presumably it is valid. + GLint max_samples = 0; + glGetIntegerv(GL_MAX_SAMPLES, &max_samples); + u32 supported_max_samples = + static_cast(std::min({max_samples, max_color_samples, max_depth_samples})); + + while (supported_max_samples > 1) + { + g_Config.backend_info.AAModes.push_back(supported_max_samples); + supported_max_samples /= 2; + } + g_Config.backend_info.AAModes.push_back(1); + // The UI wants ascending order + std::reverse(g_Config.backend_info.AAModes.begin(), g_Config.backend_info.AAModes.end()); + } + } + else + { + g_Config.backend_info.AAModes = {1}; + } const bool bSupportsIsHelperInvocation = g_ogl_config.bIsES ? g_ogl_config.eSupportedGLSLVersion >= GlslEs320 : diff --git a/Source/Core/VideoBackends/OGL/OGLConfig.h b/Source/Core/VideoBackends/OGL/OGLConfig.h index 4929901b09..70ad6ad1eb 100644 --- a/Source/Core/VideoBackends/OGL/OGLConfig.h +++ b/Source/Core/VideoBackends/OGL/OGLConfig.h @@ -81,8 +81,6 @@ struct VideoConfig const char* gl_vendor; const char* gl_renderer; const char* gl_version; - - s32 max_samples; }; void InitDriverInfo(); diff --git a/Source/Core/VideoBackends/OGL/OGLGfx.cpp b/Source/Core/VideoBackends/OGL/OGLGfx.cpp index a89f05626b..cc4c34c3de 100644 --- a/Source/Core/VideoBackends/OGL/OGLGfx.cpp +++ b/Source/Core/VideoBackends/OGL/OGLGfx.cpp @@ -146,12 +146,6 @@ OGLGfx::OGLGfx(std::unique_ptr main_gl_context, float backbuffer_scal } } - if (!PopulateConfig(m_main_gl_context.get())) - { - // Not all needed extensions are supported, so we have to stop here. - // Else some of the next calls might crash. - return; - } InitDriverInfo(); // Setup Debug logging diff --git a/Source/Core/VideoBackends/OGL/OGLMain.cpp b/Source/Core/VideoBackends/OGL/OGLMain.cpp index ef25e40a2a..13f47a054f 100644 --- a/Source/Core/VideoBackends/OGL/OGLMain.cpp +++ b/Source/Core/VideoBackends/OGL/OGLMain.cpp @@ -142,7 +142,7 @@ bool VideoBackend::FillBackendInfo(GLContext* context) g_Config.backend_info.bSupportsGPUTextureDecoding = true; g_Config.backend_info.bSupportsBBox = true; - // Overwritten in OGLRender.cpp later + // Overwritten in OGLConfig.cpp later g_Config.backend_info.bSupportsDualSourceBlend = true; g_Config.backend_info.bSupportsPrimitiveRestart = true; g_Config.backend_info.bSupportsPaletteConversion = true; @@ -182,6 +182,13 @@ bool VideoBackend::FillBackendInfo(GLContext* context) return false; } + if (!PopulateConfig(context)) + { + // Not all needed extensions are supported, so we have to stop here. + // Else some of the next calls might crash. + return false; + } + // TODO: Move the remaining fields from the Renderer constructor here. return true; } diff --git a/Source/Core/VideoBackends/OGL/OGLTexture.cpp b/Source/Core/VideoBackends/OGL/OGLTexture.cpp index f356e52d32..b4af699d73 100644 --- a/Source/Core/VideoBackends/OGL/OGLTexture.cpp +++ b/Source/Core/VideoBackends/OGL/OGLTexture.cpp @@ -15,9 +15,7 @@ namespace OGL { -namespace -{ -GLenum GetGLInternalFormatForTextureFormat(AbstractTextureFormat format, bool storage) +GLenum OGLTexture::GetGLInternalFormatForTextureFormat(AbstractTextureFormat format, bool storage) { switch (format) { @@ -55,6 +53,8 @@ GLenum GetGLInternalFormatForTextureFormat(AbstractTextureFormat format, bool st } } +namespace +{ GLenum GetGLFormatForTextureFormat(AbstractTextureFormat format) { switch (format) diff --git a/Source/Core/VideoBackends/OGL/OGLTexture.h b/Source/Core/VideoBackends/OGL/OGLTexture.h index f80aa98725..d829bf0fa5 100644 --- a/Source/Core/VideoBackends/OGL/OGLTexture.h +++ b/Source/Core/VideoBackends/OGL/OGLTexture.h @@ -36,6 +36,7 @@ public: { return IsMultisampled() ? GL_TEXTURE_2D_MULTISAMPLE_ARRAY : GL_TEXTURE_2D_ARRAY; } + static GLenum GetGLInternalFormatForTextureFormat(AbstractTextureFormat format, bool storage); GLenum GetGLFormatForImageTexture() const; private: From ac48b2eea43164349e6b112604d44490a4d731c5 Mon Sep 17 00:00:00 2001 From: Pokechu22 Date: Sun, 9 Apr 2023 23:15:41 -0700 Subject: [PATCH 3/3] EnhancementsWidget: Handle gaps in AA mode list Mesa (llvmpipe) only reports 4x MSAA, and doesn't report 2x (or 1x, but we implicitly add that). The old logic did not handle this correctly, causing selecting 4x to fail and fall back to None. This also removes VideoUtils::GetAvailableAntialiasingModes, and thus VideoUtils entirely, as its only other function was removed in 1f74653501fec1dd059705f8a3eff1edb259d4d9. --- Source/Core/DolphinLib.props | 2 - .../Config/Graphics/EnhancementsWidget.cpp | 50 +++++++++++-------- Source/Core/UICommon/CMakeLists.txt | 2 - Source/Core/UICommon/VideoUtils.cpp | 43 ---------------- Source/Core/UICommon/VideoUtils.h | 12 ----- 5 files changed, 28 insertions(+), 81 deletions(-) delete mode 100644 Source/Core/UICommon/VideoUtils.cpp delete mode 100644 Source/Core/UICommon/VideoUtils.h diff --git a/Source/Core/DolphinLib.props b/Source/Core/DolphinLib.props index 05142ae672..ec9ac2065a 100644 --- a/Source/Core/DolphinLib.props +++ b/Source/Core/DolphinLib.props @@ -534,7 +534,6 @@ - @@ -1160,7 +1159,6 @@ - diff --git a/Source/Core/DolphinQt/Config/Graphics/EnhancementsWidget.cpp b/Source/Core/DolphinQt/Config/Graphics/EnhancementsWidget.cpp index 113c9fe835..c5889d2ad4 100644 --- a/Source/Core/DolphinQt/Config/Graphics/EnhancementsWidget.cpp +++ b/Source/Core/DolphinQt/Config/Graphics/EnhancementsWidget.cpp @@ -23,8 +23,6 @@ #include "DolphinQt/QtUtils/NonDefaultQPushButton.h" #include "DolphinQt/Settings.h" -#include "UICommon/VideoUtils.h" - #include "VideoCommon/PostProcessing.h" #include "VideoCommon/VideoBackendBase.h" #include "VideoCommon/VideoCommon.h" @@ -260,18 +258,38 @@ void EnhancementsWidget::LoadSettings() m_block_save = true; // Anti-Aliasing - const int aa_selection = Config::Get(Config::GFX_MSAA); + const u32 aa_selection = Config::Get(Config::GFX_MSAA); const bool ssaa = Config::Get(Config::GFX_SSAA); const int aniso = Config::Get(Config::GFX_ENHANCE_MAX_ANISOTROPY); const TextureFilteringMode tex_filter_mode = Config::Get(Config::GFX_ENHANCE_FORCE_TEXTURE_FILTERING); m_aa_combo->clear(); - for (const auto& option : VideoUtils::GetAvailableAntialiasingModes(m_msaa_modes)) - m_aa_combo->addItem(option == "None" ? tr("None") : QString::fromStdString(option)); - m_aa_combo->setCurrentText( - QString::fromStdString(std::to_string(aa_selection) + "x " + (ssaa ? "SSAA" : "MSAA"))); + for (const u32 aa_mode : g_Config.backend_info.AAModes) + { + if (aa_mode == 1) + m_aa_combo->addItem(tr("None"), 1); + else + m_aa_combo->addItem(tr("%1x MSAA").arg(aa_mode), static_cast(aa_mode)); + + if (aa_mode == aa_selection && !ssaa) + m_aa_combo->setCurrentIndex(m_aa_combo->count() - 1); + } + if (g_Config.backend_info.bSupportsSSAA) + { + for (const u32 aa_mode : g_Config.backend_info.AAModes) + { + if (aa_mode != 1) // don't show "None" twice + { + // Mark SSAA using negative values in the variant + m_aa_combo->addItem(tr("%1x SSAA").arg(aa_mode), -static_cast(aa_mode)); + if (aa_mode == aa_selection && ssaa) + m_aa_combo->setCurrentIndex(m_aa_combo->count() - 1); + } + } + } + m_aa_combo->setEnabled(m_aa_combo->count() > 1); switch (tex_filter_mode) @@ -310,22 +328,10 @@ void EnhancementsWidget::SaveSettings() if (m_block_save) return; - bool is_ssaa = m_aa_combo->currentText().endsWith(QStringLiteral("SSAA")); - - int aa_value = m_aa_combo->currentIndex(); - - if (aa_value == 0) - { - aa_value = 1; - } - else - { - if (aa_value > m_msaa_modes) - aa_value -= m_msaa_modes; - aa_value = std::pow(2, aa_value); - } - Config::SetBaseOrCurrent(Config::GFX_MSAA, static_cast(aa_value)); + const u32 aa_value = static_cast(std::abs(m_aa_combo->currentData().toInt())); + const bool is_ssaa = m_aa_combo->currentData().toInt() < 0; + Config::SetBaseOrCurrent(Config::GFX_MSAA, aa_value); Config::SetBaseOrCurrent(Config::GFX_SSAA, is_ssaa); const int texture_filtering_selection = m_texture_filtering_combo->currentData().toInt(); diff --git a/Source/Core/UICommon/CMakeLists.txt b/Source/Core/UICommon/CMakeLists.txt index f2ffbd0821..947aeae346 100644 --- a/Source/Core/UICommon/CMakeLists.txt +++ b/Source/Core/UICommon/CMakeLists.txt @@ -23,8 +23,6 @@ add_library(uicommon UICommon.h USBUtils.cpp USBUtils.h - VideoUtils.cpp - VideoUtils.h ) target_link_libraries(uicommon diff --git a/Source/Core/UICommon/VideoUtils.cpp b/Source/Core/UICommon/VideoUtils.cpp deleted file mode 100644 index 17947e81b2..0000000000 --- a/Source/Core/UICommon/VideoUtils.cpp +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2017 Dolphin Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "UICommon/VideoUtils.h" - -#include "Common/Assert.h" -#include "VideoCommon/VideoConfig.h" - -namespace VideoUtils -{ -std::vector GetAvailableAntialiasingModes(int& msaa_modes) -{ - std::vector modes; - const auto& aa_modes = g_Config.backend_info.AAModes; - const bool supports_ssaa = g_Config.backend_info.bSupportsSSAA; - msaa_modes = 0; - - for (const auto mode : aa_modes) - { - if (mode == 1) - { - modes.push_back("None"); - ASSERT_MSG(VIDEO, !supports_ssaa || msaa_modes == 0, "SSAA setting won't work correctly"); - } - else - { - modes.push_back(std::to_string(mode) + "x MSAA"); - msaa_modes++; - } - } - - if (supports_ssaa) - { - for (const auto mode : aa_modes) - { - if (mode != 1) - modes.push_back(std::to_string(mode) + "x SSAA"); - } - } - - return modes; -} -} // namespace VideoUtils diff --git a/Source/Core/UICommon/VideoUtils.h b/Source/Core/UICommon/VideoUtils.h deleted file mode 100644 index 492813adab..0000000000 --- a/Source/Core/UICommon/VideoUtils.h +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2017 Dolphin Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include -#include - -namespace VideoUtils -{ -std::vector GetAvailableAntialiasingModes(int& m_msaa_modes); -} // namespace VideoUtils