Merge pull request #11699 from Pokechu22/gl-check-maximum-samples

OpenGL: Check the list of supported AA modes instead of hardcoding
This commit is contained in:
Admiral H. Curtiss 2023-06-09 15:07:07 +02:00 committed by GitHub
commit 8f51a9d2d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 237 additions and 158 deletions

View File

@ -1674,7 +1674,7 @@ const GLFunc gl_function_array[] = {
GLFUNC_REQUIRES(glDrawArraysInstancedBaseInstance, "VERSION_4_2"), GLFUNC_REQUIRES(glDrawArraysInstancedBaseInstance, "VERSION_4_2"),
GLFUNC_REQUIRES(glDrawElementsInstancedBaseInstance, "VERSION_4_2"), GLFUNC_REQUIRES(glDrawElementsInstancedBaseInstance, "VERSION_4_2"),
GLFUNC_REQUIRES(glDrawElementsInstancedBaseVertexBaseInstance, "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(glGetActiveAtomicCounterBufferiv, "VERSION_4_2"),
GLFUNC_REQUIRES(glBindImageTexture, "VERSION_4_2"), GLFUNC_REQUIRES(glBindImageTexture, "VERSION_4_2"),
GLFUNC_REQUIRES(glMemoryBarrier, "VERSION_4_2"), GLFUNC_REQUIRES(glMemoryBarrier, "VERSION_4_2"),

View File

@ -261,7 +261,7 @@ bool Init(std::unique_ptr<BootParameters> boot, const WindowSystemInfo& wsi)
Host_UpdateMainFrame(); // Disable any menus or buttons at boot Host_UpdateMainFrame(); // Disable any menus or buttons at boot
// Manually reactivate the video backend in case a GameINI overrides the video backend setting. // 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. // Issue any API calls which must occur on the main thread for the graphics backend.
WindowSystemInfo prepared_wsi(wsi); WindowSystemInfo prepared_wsi(wsi);
@ -579,7 +579,7 @@ static void EmuThread(std::unique_ptr<BootParameters> boot, WindowSystemInfo wsi
system.GetPowerPC().GetDebugInterface().Clear(guard); system.GetPowerPC().GetDebugInterface().Clear(guard);
}}; }};
VideoBackendBase::PopulateBackendInfo(); VideoBackendBase::PopulateBackendInfo(wsi);
if (!g_video_backend->Initialize(wsi)) if (!g_video_backend->Initialize(wsi))
{ {

View File

@ -534,7 +534,6 @@
<ClInclude Include="UICommon\ResourcePack\ResourcePack.h" /> <ClInclude Include="UICommon\ResourcePack\ResourcePack.h" />
<ClInclude Include="UICommon\UICommon.h" /> <ClInclude Include="UICommon\UICommon.h" />
<ClInclude Include="UICommon\USBUtils.h" /> <ClInclude Include="UICommon\USBUtils.h" />
<ClInclude Include="UICommon\VideoUtils.h" />
<ClInclude Include="UpdaterCommon\UI.h" /> <ClInclude Include="UpdaterCommon\UI.h" />
<ClInclude Include="UpdaterCommon\UpdaterCommon.h" /> <ClInclude Include="UpdaterCommon\UpdaterCommon.h" />
<ClInclude Include="VideoBackends\D3D\D3DBase.h" /> <ClInclude Include="VideoBackends\D3D\D3DBase.h" />
@ -1160,7 +1159,6 @@
<ClCompile Include="UICommon\ResourcePack\ResourcePack.cpp" /> <ClCompile Include="UICommon\ResourcePack\ResourcePack.cpp" />
<ClCompile Include="UICommon\UICommon.cpp" /> <ClCompile Include="UICommon\UICommon.cpp" />
<ClCompile Include="UICommon\USBUtils.cpp" /> <ClCompile Include="UICommon\USBUtils.cpp" />
<ClCompile Include="UICommon\VideoUtils.cpp" />
<ClCompile Include="UpdaterCommon\UpdaterCommon.cpp" /> <ClCompile Include="UpdaterCommon\UpdaterCommon.cpp" />
<ClCompile Include="VideoBackends\D3D\D3DBase.cpp" /> <ClCompile Include="VideoBackends\D3D\D3DBase.cpp" />
<ClCompile Include="VideoBackends\D3D\D3DBoundingBox.cpp" /> <ClCompile Include="VideoBackends\D3D\D3DBoundingBox.cpp" />

View File

@ -23,8 +23,6 @@
#include "DolphinQt/QtUtils/NonDefaultQPushButton.h" #include "DolphinQt/QtUtils/NonDefaultQPushButton.h"
#include "DolphinQt/Settings.h" #include "DolphinQt/Settings.h"
#include "UICommon/VideoUtils.h"
#include "VideoCommon/PostProcessing.h" #include "VideoCommon/PostProcessing.h"
#include "VideoCommon/VideoBackendBase.h" #include "VideoCommon/VideoBackendBase.h"
#include "VideoCommon/VideoCommon.h" #include "VideoCommon/VideoCommon.h"
@ -260,18 +258,38 @@ void EnhancementsWidget::LoadSettings()
m_block_save = true; m_block_save = true;
// Anti-Aliasing // 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 bool ssaa = Config::Get(Config::GFX_SSAA);
const int aniso = Config::Get(Config::GFX_ENHANCE_MAX_ANISOTROPY); const int aniso = Config::Get(Config::GFX_ENHANCE_MAX_ANISOTROPY);
const TextureFilteringMode tex_filter_mode = const TextureFilteringMode tex_filter_mode =
Config::Get(Config::GFX_ENHANCE_FORCE_TEXTURE_FILTERING); Config::Get(Config::GFX_ENHANCE_FORCE_TEXTURE_FILTERING);
m_aa_combo->clear(); 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( for (const u32 aa_mode : g_Config.backend_info.AAModes)
QString::fromStdString(std::to_string(aa_selection) + "x " + (ssaa ? "SSAA" : "MSAA"))); {
if (aa_mode == 1)
m_aa_combo->addItem(tr("None"), 1);
else
m_aa_combo->addItem(tr("%1x MSAA").arg(aa_mode), static_cast<int>(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<int>(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); m_aa_combo->setEnabled(m_aa_combo->count() > 1);
switch (tex_filter_mode) switch (tex_filter_mode)
@ -310,22 +328,10 @@ void EnhancementsWidget::SaveSettings()
if (m_block_save) if (m_block_save)
return; return;
bool is_ssaa = m_aa_combo->currentText().endsWith(QStringLiteral("SSAA")); const u32 aa_value = static_cast<u32>(std::abs(m_aa_combo->currentData().toInt()));
const bool is_ssaa = m_aa_combo->currentData().toInt() < 0;
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<unsigned int>(aa_value));
Config::SetBaseOrCurrent(Config::GFX_MSAA, aa_value);
Config::SetBaseOrCurrent(Config::GFX_SSAA, is_ssaa); Config::SetBaseOrCurrent(Config::GFX_SSAA, is_ssaa);
const int texture_filtering_selection = m_texture_filtering_combo->currentData().toInt(); const int texture_filtering_selection = m_texture_filtering_combo->currentData().toInt();

View File

@ -24,7 +24,7 @@
#include "VideoCommon/VideoBackendBase.h" #include "VideoCommon/VideoBackendBase.h"
#include "VideoCommon/VideoConfig.h" #include "VideoCommon/VideoConfig.h"
GraphicsWindow::GraphicsWindow(MainWindow* parent) : QDialog(parent) GraphicsWindow::GraphicsWindow(MainWindow* parent) : QDialog(parent), m_main_window(parent)
{ {
CreateMainLayout(); CreateMainLayout();
@ -68,7 +68,7 @@ void GraphicsWindow::CreateMainLayout()
void GraphicsWindow::OnBackendChanged(const QString& backend_name) void GraphicsWindow::OnBackendChanged(const QString& backend_name)
{ {
Config::SetBase(Config::MAIN_GFX_BACKEND, backend_name.toStdString()); Config::SetBase(Config::MAIN_GFX_BACKEND, backend_name.toStdString());
VideoBackendBase::PopulateBackendInfoFromUI(); VideoBackendBase::PopulateBackendInfoFromUI(m_main_window->GetWindowSystemInfo());
setWindowTitle( setWindowTitle(
tr("%1 Graphics Configuration").arg(tr(g_video_backend->GetDisplayName().c_str()))); tr("%1 Graphics Configuration").arg(tr(g_video_backend->GetDisplayName().c_str())));

View File

@ -28,4 +28,6 @@ signals:
private: private:
void CreateMainLayout(); void CreateMainLayout();
void OnBackendChanged(const QString& backend); void OnBackendChanged(const QString& backend);
MainWindow* const m_main_window;
}; };

View File

@ -343,12 +343,17 @@ MainWindow::~MainWindow()
Config::Save(); Config::Save();
} }
WindowSystemInfo MainWindow::GetWindowSystemInfo() const
{
return ::GetWindowSystemInfo(m_render_widget->windowHandle());
}
void MainWindow::InitControllers() void MainWindow::InitControllers()
{ {
if (g_controller_interface.IsInit()) if (g_controller_interface.IsInit())
return; return;
UICommon::InitControllers(GetWindowSystemInfo(windowHandle())); UICommon::InitControllers(::GetWindowSystemInfo(windowHandle()));
m_hotkey_scheduler = new HotkeyScheduler(); m_hotkey_scheduler = new HotkeyScheduler();
m_hotkey_scheduler->Start(); m_hotkey_scheduler->Start();
@ -1098,7 +1103,7 @@ void MainWindow::StartGame(std::unique_ptr<BootParameters>&& parameters)
// Boot up, show an error if it fails to load the game. // Boot up, show an error if it fails to load the game.
if (!BootManager::BootCore(std::move(parameters), 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); ModalMessageBox::critical(this, tr("Error"), tr("Failed to init core"), QMessageBox::Ok);
HideRenderWidget(); 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 // 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 // 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. // 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 : is_exit ? ControllerInterface::WindowChangeReason::Exit :
ControllerInterface::WindowChangeReason::Other); ControllerInterface::WindowChangeReason::Other);
} }

View File

@ -50,6 +50,7 @@ class ThreadWidget;
class ToolBar; class ToolBar;
class WatchWidget; class WatchWidget;
class WiiTASInputWindow; class WiiTASInputWindow;
struct WindowSystemInfo;
namespace DiscIO namespace DiscIO
{ {
@ -76,6 +77,7 @@ public:
~MainWindow(); ~MainWindow();
void Show(); void Show();
WindowSystemInfo GetWindowSystemInfo() const;
bool eventFilter(QObject* object, QEvent* event) override; bool eventFilter(QObject* object, QEvent* event) override;

View File

@ -23,8 +23,6 @@ add_library(uicommon
UICommon.h UICommon.h
USBUtils.cpp USBUtils.cpp
USBUtils.h USBUtils.h
VideoUtils.cpp
VideoUtils.h
) )
target_link_libraries(uicommon target_link_libraries(uicommon

View File

@ -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<std::string> GetAvailableAntialiasingModes(int& msaa_modes)
{
std::vector<std::string> 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

View File

@ -1,12 +0,0 @@
// Copyright 2017 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <string>
#include <vector>
namespace VideoUtils
{
std::vector<std::string> GetAvailableAntialiasingModes(int& m_msaa_modes);
} // namespace VideoUtils

View File

@ -63,7 +63,7 @@ std::optional<std::string> VideoBackend::GetWarningMessage() const
return result; return result;
} }
void VideoBackend::InitBackendInfo() void VideoBackend::InitBackendInfo(const WindowSystemInfo& wsi)
{ {
if (!D3DCommon::LoadLibraries()) if (!D3DCommon::LoadLibraries())
return; return;

View File

@ -18,7 +18,7 @@ public:
std::string GetDisplayName() const override; std::string GetDisplayName() const override;
std::optional<std::string> GetWarningMessage() const override; std::optional<std::string> GetWarningMessage() const override;
void InitBackendInfo() override; void InitBackendInfo(const WindowSystemInfo& wsi) override;
static constexpr const char* NAME = "D3D"; static constexpr const char* NAME = "D3D";

View File

@ -36,7 +36,7 @@ std::string VideoBackend::GetDisplayName() const
return "Direct3D 12"; return "Direct3D 12";
} }
void VideoBackend::InitBackendInfo() void VideoBackend::InitBackendInfo(const WindowSystemInfo& wsi)
{ {
if (!D3DCommon::LoadLibraries()) if (!D3DCommon::LoadLibraries())
return; return;

View File

@ -16,7 +16,7 @@ public:
std::string GetName() const override; std::string GetName() const override;
std::string GetDisplayName() const override; std::string GetDisplayName() const override;
void InitBackendInfo() override; void InitBackendInfo(const WindowSystemInfo& wsi) override;
static constexpr const char* NAME = "D3D12"; static constexpr const char* NAME = "D3D12";

View File

@ -119,7 +119,7 @@ void Metal::VideoBackend::Shutdown()
ObjectCache::Shutdown(); ObjectCache::Shutdown();
} }
void Metal::VideoBackend::InitBackendInfo() void Metal::VideoBackend::InitBackendInfo(const WindowSystemInfo& wsi)
{ {
@autoreleasepool @autoreleasepool
{ {

View File

@ -18,7 +18,7 @@ public:
std::string GetDisplayName() const override; std::string GetDisplayName() const override;
std::optional<std::string> GetWarningMessage() const override; std::optional<std::string> GetWarningMessage() const override;
void InitBackendInfo() override; void InitBackendInfo(const WindowSystemInfo& wsi) override;
void PrepareWindow(WindowSystemInfo& wsi) override; void PrepareWindow(WindowSystemInfo& wsi) override;

View File

@ -25,7 +25,7 @@
namespace Null namespace Null
{ {
void VideoBackend::InitBackendInfo() void VideoBackend::InitBackendInfo(const WindowSystemInfo& wsi)
{ {
g_Config.backend_info.api_type = APIType::Nothing; g_Config.backend_info.api_type = APIType::Nothing;
g_Config.backend_info.MaxTextureSize = 16384; g_Config.backend_info.MaxTextureSize = 16384;

View File

@ -15,7 +15,7 @@ public:
std::string GetName() const override { return NAME; } std::string GetName() const override { return NAME; }
std::string GetDisplayName() const override; std::string GetDisplayName() const override;
void InitBackendInfo() override; void InitBackendInfo(const WindowSystemInfo& wsi) override;
static constexpr const char* NAME = "Null"; static constexpr const char* NAME = "Null";
}; };

View File

@ -3,6 +3,11 @@
#include "VideoBackends/OGL/OGLConfig.h" #include "VideoBackends/OGL/OGLConfig.h"
#include <cstdio>
#include <string>
#include <string_view>
#include "Common/Assert.h"
#include "Common/GL/GLContext.h" #include "Common/GL/GLContext.h"
#include "Common/GL/GLExtensions/GLExtensions.h" #include "Common/GL/GLExtensions/GLExtensions.h"
#include "Common/Logging/LogManager.h" #include "Common/Logging/LogManager.h"
@ -10,14 +15,13 @@
#include "Core/Config/GraphicsSettings.h" #include "Core/Config/GraphicsSettings.h"
#include "VideoBackends/OGL/OGLTexture.h"
#include "VideoCommon/DriverDetails.h" #include "VideoCommon/DriverDetails.h"
#include "VideoCommon/FramebufferManager.h"
#include "VideoCommon/OnScreenDisplay.h" #include "VideoCommon/OnScreenDisplay.h"
#include "VideoCommon/VideoConfig.h" #include "VideoCommon/VideoConfig.h"
#include <cstdio>
#include <string>
#include <string_view>
namespace OGL namespace OGL
{ {
void InitDriverInfo() void InitDriverInfo()
@ -537,9 +541,118 @@ bool PopulateConfig(GLContext* m_main_gl_context)
g_Config.backend_info.bSupportsEarlyZ = g_Config.backend_info.bSupportsEarlyZ =
g_ogl_config.bSupportsImageLoadStore || g_ogl_config.bSupportsConservativeDepth; g_ogl_config.bSupportsImageLoadStore || g_ogl_config.bSupportsConservativeDepth;
glGetIntegerv(GL_MAX_SAMPLES, &g_ogl_config.max_samples); g_Config.backend_info.AAModes.clear();
if (g_ogl_config.max_samples < 1 || !g_ogl_config.bSupportsMSAA) if (g_ogl_config.bSupportsMSAA)
g_ogl_config.max_samples = 1; {
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<int> 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<GLint*>(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<int> 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<GLint*>(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<u32>(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 ? const bool bSupportsIsHelperInvocation = g_ogl_config.bIsES ?
g_ogl_config.eSupportedGLSLVersion >= GlslEs320 : g_ogl_config.eSupportedGLSLVersion >= GlslEs320 :

View File

@ -82,8 +82,6 @@ struct VideoConfig
const char* gl_vendor; const char* gl_vendor;
const char* gl_renderer; const char* gl_renderer;
const char* gl_version; const char* gl_version;
s32 max_samples;
}; };
void InitDriverInfo(); void InitDriverInfo();

View File

@ -146,12 +146,6 @@ OGLGfx::OGLGfx(std::unique_ptr<GLContext> 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(); InitDriverInfo();
// Setup Debug logging // Setup Debug logging

View File

@ -74,8 +74,45 @@ std::string VideoBackend::GetDisplayName() const
return _trans("OpenGL"); return _trans("OpenGL");
} }
void VideoBackend::InitBackendInfo() void VideoBackend::InitBackendInfo(const WindowSystemInfo& wsi)
{ {
std::unique_ptr<GLContext> 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.api_type = APIType::OpenGL;
g_Config.backend_info.MaxTextureSize = 16384; g_Config.backend_info.MaxTextureSize = 16384;
g_Config.backend_info.bUsesLowerLeftOrigin = true; g_Config.backend_info.bUsesLowerLeftOrigin = true;
@ -105,7 +142,7 @@ void VideoBackend::InitBackendInfo()
g_Config.backend_info.bSupportsGPUTextureDecoding = true; g_Config.backend_info.bSupportsGPUTextureDecoding = true;
g_Config.backend_info.bSupportsBBox = 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.bSupportsDualSourceBlend = true;
g_Config.backend_info.bSupportsPrimitiveRestart = true; g_Config.backend_info.bSupportsPrimitiveRestart = true;
g_Config.backend_info.bSupportsPaletteConversion = true; g_Config.backend_info.bSupportsPaletteConversion = true;
@ -123,33 +160,6 @@ void VideoBackend::InitBackendInfo()
// aamodes - 1 is to stay consistent with D3D (means no AA) // aamodes - 1 is to stay consistent with D3D (means no AA)
g_Config.backend_info.AAModes = {1, 2, 4, 8}; 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 // check for the max vertex attributes
GLint numvertexattribs = 0; GLint numvertexattribs = 0;
@ -172,6 +182,13 @@ bool VideoBackend::FillBackendInfo()
return false; 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. // TODO: Move the remaining fields from the Renderer constructor here.
return true; return true;
} }
@ -184,7 +201,7 @@ bool VideoBackend::Initialize(const WindowSystemInfo& wsi)
if (!main_gl_context) if (!main_gl_context)
return false; return false;
if (!InitializeGLExtensions(main_gl_context.get()) || !FillBackendInfo()) if (!FillBackendInfo(main_gl_context.get()))
return false; return false;
auto gfx = std::make_unique<OGLGfx>(std::move(main_gl_context), wsi.render_surface_scale); auto gfx = std::make_unique<OGLGfx>(std::move(main_gl_context), wsi.render_surface_scale);

View File

@ -15,9 +15,7 @@
namespace OGL namespace OGL
{ {
namespace GLenum OGLTexture::GetGLInternalFormatForTextureFormat(AbstractTextureFormat format, bool storage)
{
GLenum GetGLInternalFormatForTextureFormat(AbstractTextureFormat format, bool storage)
{ {
switch (format) switch (format)
{ {
@ -55,6 +53,8 @@ GLenum GetGLInternalFormatForTextureFormat(AbstractTextureFormat format, bool st
} }
} }
namespace
{
GLenum GetGLFormatForTextureFormat(AbstractTextureFormat format) GLenum GetGLFormatForTextureFormat(AbstractTextureFormat format)
{ {
switch (format) switch (format)

View File

@ -36,6 +36,7 @@ public:
{ {
return IsMultisampled() ? GL_TEXTURE_2D_MULTISAMPLE_ARRAY : GL_TEXTURE_2D_ARRAY; return IsMultisampled() ? GL_TEXTURE_2D_MULTISAMPLE_ARRAY : GL_TEXTURE_2D_ARRAY;
} }
static GLenum GetGLInternalFormatForTextureFormat(AbstractTextureFormat format, bool storage);
GLenum GetGLFormatForImageTexture() const; GLenum GetGLFormatForImageTexture() const;
private: private:

View File

@ -19,12 +19,12 @@ public:
std::string GetName() const override; std::string GetName() const override;
std::string GetDisplayName() const override; std::string GetDisplayName() const override;
void InitBackendInfo() override; void InitBackendInfo(const WindowSystemInfo& wsi) override;
static constexpr const char* NAME = "OGL"; static constexpr const char* NAME = "OGL";
private: private:
bool InitializeGLExtensions(GLContext* context); bool InitializeGLExtensions(GLContext* context);
bool FillBackendInfo(); bool FillBackendInfo(GLContext* context);
}; };
} // namespace OGL } // namespace OGL

View File

@ -62,7 +62,7 @@ std::optional<std::string> VideoSoftware::GetWarningMessage() const
"really want to enable software rendering? If unsure, select 'No'."); "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.api_type = APIType::Nothing;
g_Config.backend_info.MaxTextureSize = 16384; g_Config.backend_info.MaxTextureSize = 16384;

View File

@ -17,7 +17,7 @@ class VideoSoftware : public VideoBackendBase
std::string GetDisplayName() const override; std::string GetDisplayName() const override;
std::optional<std::string> GetWarningMessage() const override; std::optional<std::string> GetWarningMessage() const override;
void InitBackendInfo() override; void InitBackendInfo(const WindowSystemInfo& wsi) override;
static constexpr const char* NAME = "Software Renderer"; static constexpr const char* NAME = "Software Renderer";
}; };

View File

@ -30,7 +30,7 @@
namespace Vulkan namespace Vulkan
{ {
void VideoBackend::InitBackendInfo() void VideoBackend::InitBackendInfo(const WindowSystemInfo& wsi)
{ {
VulkanContext::PopulateBackendInfo(&g_Config); VulkanContext::PopulateBackendInfo(&g_Config);

View File

@ -16,7 +16,7 @@ public:
std::string GetName() const override { return NAME; } std::string GetName() const override { return NAME; }
std::string GetDisplayName() const override { return _trans("Vulkan"); } std::string GetDisplayName() const override { return _trans("Vulkan"); }
void InitBackendInfo() override; void InitBackendInfo(const WindowSystemInfo& wsi) override;
void PrepareWindow(WindowSystemInfo& wsi) override; void PrepareWindow(WindowSystemInfo& wsi) override;
static constexpr const char* NAME = "Vulkan"; static constexpr const char* NAME = "Vulkan";

View File

@ -281,7 +281,7 @@ void VideoBackendBase::ActivateBackend(const std::string& name)
g_video_backend = iter->get(); g_video_backend = iter->get();
} }
void VideoBackendBase::PopulateBackendInfo() void VideoBackendBase::PopulateBackendInfo(const WindowSystemInfo& wsi)
{ {
g_Config.Refresh(); g_Config.Refresh();
// Reset backend_info so if the backend forgets to initialize something it doesn't end up using // 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 = {}; g_Config.backend_info = {};
ActivateBackend(Config::Get(Config::MAIN_GFX_BACKEND)); ActivateBackend(Config::Get(Config::MAIN_GFX_BACKEND));
g_Config.backend_info.DisplayName = g_video_backend->GetDisplayName(); 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 // 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. // such as anti-aliasing, or the selected adapter may be invalid, and should be checked.
g_Config.VerifyValidity(); 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 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 we did it here, the UI thread can race with the with the GPU thread.
if (!Core::IsRunning()) if (!Core::IsRunning())
PopulateBackendInfo(); PopulateBackendInfo(wsi);
} }
void VideoBackendBase::DoState(PointerWrap& p) void VideoBackendBase::DoState(PointerWrap& p)

View File

@ -47,7 +47,7 @@ public:
virtual std::string GetName() const = 0; virtual std::string GetName() const = 0;
virtual std::string GetDisplayName() const { return GetName(); } virtual std::string GetDisplayName() const { return GetName(); }
virtual void InitBackendInfo() = 0; virtual void InitBackendInfo(const WindowSystemInfo& wsi) = 0;
virtual std::optional<std::string> GetWarningMessage() const { return {}; } virtual std::optional<std::string> GetWarningMessage() const { return {}; }
// Prepares a native window for rendering. This is called on the main thread, or the // 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); static void ActivateBackend(const std::string& name);
// Fills the backend_info fields with the capabilities of the selected backend/device. // 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. // 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. // Wrapper function which pushes the event to the GPU thread.
void DoState(PointerWrap& p); void DoState(PointerWrap& p);