mirror of https://github.com/PCSX2/pcsx2.git
GS: Uncap upscale multiplier subject to GPU limits
This commit is contained in:
parent
46e30467de
commit
315d30fe4c
|
@ -140,13 +140,6 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget*
|
|||
//////////////////////////////////////////////////////////////////////////
|
||||
// HW Settings
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
static const char* upscale_entries[] = {"Native (PS2) (Default)", "1.25x Native", "1.5x Native", "1.75x Native", "2x Native (~720p)",
|
||||
"2.25x Native", "2.5x Native", "2.75x Native", "3x Native (~1080p)", "3.5x Native", "4x Native (~1440p/2K)", "5x Native (~1620p)",
|
||||
"6x Native (~2160p/4K)", "7x Native (~2520p)", "8x Native (~2880p/5K)", nullptr};
|
||||
static const char* upscale_values[] = {
|
||||
"1", "1.25", "1.5", "1.75", "2", "2.25", "2.5", "2.75", "3", "3.5", "4", "5", "6", "7", "8", nullptr};
|
||||
SettingWidgetBinder::BindWidgetToEnumSetting(
|
||||
sif, m_ui.upscaleMultiplier, "EmuCore/GS", "upscale_multiplier", upscale_entries, upscale_values, "1.0");
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.textureFiltering, "EmuCore/GS", "filter", static_cast<int>(BiFiltering::PS2));
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(
|
||||
sif, m_ui.trilinearFiltering, "EmuCore/GS", "TriFilter", static_cast<int>(TriFiltering::Automatic), -1);
|
||||
|
@ -158,6 +151,8 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget*
|
|||
sif, m_ui.blending, "EmuCore/GS", "accurate_blending_unit", static_cast<int>(AccBlendLevel::Basic));
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(
|
||||
sif, m_ui.texturePreloading, "EmuCore/GS", "texture_preloading", static_cast<int>(TexturePreloadingLevel::Off));
|
||||
connect(m_ui.upscaleMultiplier, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
|
||||
&GraphicsSettingsWidget::onUpscaleMultiplierChanged);
|
||||
connect(m_ui.trilinearFiltering, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
|
||||
&GraphicsSettingsWidget::onTrilinearFilteringChanged);
|
||||
onTrilinearFilteringChanged();
|
||||
|
@ -1036,10 +1031,9 @@ void GraphicsSettingsWidget::updateRendererDependentOptions()
|
|||
m_ui.exclusiveFullscreenControl->setEnabled(is_auto || is_vk);
|
||||
|
||||
// populate adapters
|
||||
std::vector<std::string> adapters;
|
||||
std::vector<std::string> fullscreen_modes;
|
||||
GSGetAdaptersAndFullscreenModes(type, &adapters, &fullscreen_modes);
|
||||
|
||||
std::vector<GSAdapterInfo> adapters = GSGetAdapterInfo(type);
|
||||
const GSAdapterInfo* current_adapter_info = nullptr;
|
||||
|
||||
// fill+select adapters
|
||||
{
|
||||
QSignalBlocker sb(m_ui.adapterDropdown);
|
||||
|
@ -1062,12 +1056,17 @@ void GraphicsSettingsWidget::updateRendererDependentOptions()
|
|||
}
|
||||
}
|
||||
|
||||
for (const std::string& adapter : adapters)
|
||||
for (const GSAdapterInfo& adapter : adapters)
|
||||
{
|
||||
m_ui.adapterDropdown->addItem(QString::fromStdString(adapter));
|
||||
if (current_adapter == adapter)
|
||||
m_ui.adapterDropdown->addItem(QString::fromStdString(adapter.name));
|
||||
if (current_adapter == adapter.name)
|
||||
{
|
||||
m_ui.adapterDropdown->setCurrentIndex(m_ui.adapterDropdown->count() - 1);
|
||||
current_adapter_info = &adapter;
|
||||
}
|
||||
}
|
||||
|
||||
current_adapter_info = (current_adapter_info || adapters.empty()) ? current_adapter_info : &adapters.front();
|
||||
}
|
||||
|
||||
// fill+select fullscreen modes
|
||||
|
@ -1090,13 +1089,90 @@ void GraphicsSettingsWidget::updateRendererDependentOptions()
|
|||
}
|
||||
}
|
||||
|
||||
for (const std::string& fs_mode : fullscreen_modes)
|
||||
if (current_adapter_info)
|
||||
{
|
||||
m_ui.fullscreenModes->addItem(QString::fromStdString(fs_mode));
|
||||
if (current_mode == fs_mode)
|
||||
m_ui.fullscreenModes->setCurrentIndex(m_ui.fullscreenModes->count() - 1);
|
||||
for (const std::string& fs_mode : current_adapter_info->fullscreen_modes)
|
||||
{
|
||||
m_ui.fullscreenModes->addItem(QString::fromStdString(fs_mode));
|
||||
if (current_mode == fs_mode)
|
||||
m_ui.fullscreenModes->setCurrentIndex(m_ui.fullscreenModes->count() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// assume the GPU can do 10K textures.
|
||||
const u32 max_upscale_multiplier = std::max(current_adapter_info ? current_adapter_info->max_upscale_multiplier : 0u, 10u);
|
||||
populateUpscaleMultipliers(max_upscale_multiplier);
|
||||
}
|
||||
|
||||
void GraphicsSettingsWidget::populateUpscaleMultipliers(u32 max_upscale_multiplier)
|
||||
{
|
||||
static constexpr std::pair<const char*, float> templates[] = {
|
||||
{QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "Native (PS2) (Default)"), 1.0f},
|
||||
{QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "1.25x Native"), 1.25f},
|
||||
{QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "1.5x Native"), 1.5f},
|
||||
{QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "1.75x Native"), 1.75f},
|
||||
{QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "2x Native (~720p)"), 2.0f},
|
||||
{QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "2.25x Native"), 2.25f},
|
||||
{QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "2.5x Native"), 2.5f},
|
||||
{QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "2.75x Native"), 2.75f},
|
||||
{QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "3x Native (~1080p)"), 3.0f},
|
||||
{QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "3.5x Native"), 3.5f},
|
||||
{QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "4x Native (~1440p/2K)"), 4.0f},
|
||||
{QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "5x Native (~1620p)"), 5.0f},
|
||||
{QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "6x Native (~2160p/4K)"), 6.0f},
|
||||
{QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "7x Native (~2520p)"), 7.0f},
|
||||
{QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "8x Native (~2880p/5K)"), 8.0f},
|
||||
};
|
||||
static constexpr u32 max_template_multiplier = 8;
|
||||
|
||||
// Limit the dropdown to 12x if we're not showing advanced settings. Save the noobs.
|
||||
static constexpr u32 max_non_advanced_multiplier = 12;
|
||||
|
||||
QSignalBlocker sb(m_ui.upscaleMultiplier);
|
||||
m_ui.upscaleMultiplier->clear();
|
||||
|
||||
for (const auto& [name, value] : templates)
|
||||
{
|
||||
if (value > max_upscale_multiplier)
|
||||
continue;
|
||||
|
||||
m_ui.upscaleMultiplier->addItem(tr(name), QVariant(value));
|
||||
}
|
||||
const u32 max_shown_multiplier = QtHost::ShouldShowAdvancedSettings() ?
|
||||
max_upscale_multiplier :
|
||||
std::min(max_upscale_multiplier, max_non_advanced_multiplier);
|
||||
for (u32 i = max_template_multiplier + 1; i <= max_shown_multiplier; i++)
|
||||
m_ui.upscaleMultiplier->addItem(tr("%1x Native ").arg(i), QVariant(static_cast<float>(i)));
|
||||
|
||||
const float global_value = Host::GetBaseFloatSettingValue("EmuCore/GS", "upscale_multiplier", 1.0f);
|
||||
if (m_dialog->isPerGameSettings())
|
||||
{
|
||||
m_ui.upscaleMultiplier->addItem(tr("Use Global Setting [%1]").arg(QStringLiteral("%1x").arg(global_value)));
|
||||
|
||||
const std::optional<float> config_value = m_dialog->getFloatValue("EmuCore/GS", "upscale_multiplier", std::nullopt);
|
||||
if (config_value.has_value())
|
||||
{
|
||||
if (int index = m_ui.upscaleMultiplier->findData(QVariant(config_value.value())); index > 0)
|
||||
m_ui.upscaleMultiplier->setCurrentIndex(index);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ui.upscaleMultiplier->setCurrentIndex(0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (int index = m_ui.upscaleMultiplier->findData(QVariant(global_value)); index > 0)
|
||||
m_ui.upscaleMultiplier->setCurrentIndex(index);
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsSettingsWidget::onUpscaleMultiplierChanged()
|
||||
{
|
||||
const QVariant data = m_ui.upscaleMultiplier->currentData();
|
||||
m_dialog->setFloatSettingValue("EmuCore/GS", "upscale_multiplier",
|
||||
data.isValid() ? std::optional<float>(data.toFloat()) : std::optional<float>());
|
||||
}
|
||||
|
||||
void GraphicsSettingsWidget::resetManualHardwareFixes()
|
||||
|
|
|
@ -29,6 +29,7 @@ private Q_SLOTS:
|
|||
void onSWTextureFilteringChange();
|
||||
void onRendererChanged(int index);
|
||||
void onAdapterChanged(int index);
|
||||
void onUpscaleMultiplierChanged();
|
||||
void onTrilinearFilteringChanged();
|
||||
void onGpuPaletteConversionChanged(int state);
|
||||
void onCPUSpriteRenderBWChanged();
|
||||
|
@ -46,6 +47,7 @@ private Q_SLOTS:
|
|||
private:
|
||||
GSRendererType getEffectiveRenderer() const;
|
||||
void updateRendererDependentOptions();
|
||||
void populateUpscaleMultipliers(u32 max_upscale_multiplier);
|
||||
void resetManualHardwareFixes();
|
||||
|
||||
SettingsWindow* m_dialog;
|
||||
|
|
|
@ -48,6 +48,8 @@
|
|||
#include "common/SmallString.h"
|
||||
#include "common/StringUtil.h"
|
||||
|
||||
#include "IconsFontAwesome5.h"
|
||||
|
||||
#include "fmt/format.h"
|
||||
|
||||
#include <fstream>
|
||||
|
@ -171,6 +173,24 @@ static void CloseGSDevice(bool clear_state)
|
|||
g_gs_device.reset();
|
||||
}
|
||||
|
||||
static void GSClampUpscaleMultiplier(Pcsx2Config::GSOptions& config)
|
||||
{
|
||||
const u32 max_upscale_multiplier = GSGetMaxUpscaleMultiplier(g_gs_device->GetMaxTextureSize());
|
||||
if (config.UpscaleMultiplier <= static_cast<float>(max_upscale_multiplier))
|
||||
{
|
||||
// Shouldn't happen, but just in case.
|
||||
if (config.UpscaleMultiplier < 1.0f)
|
||||
config.UpscaleMultiplier = 1.0f;
|
||||
return;
|
||||
}
|
||||
|
||||
Host::AddIconOSDMessage("GSUpscaleMultiplierInvalid", ICON_FA_EXCLAMATION_TRIANGLE,
|
||||
fmt::format(TRANSLATE_FS("GS", "Configured upscale multiplier {}x is above your GPU's supported multiplier of {}x."),
|
||||
config.UpscaleMultiplier, max_upscale_multiplier),
|
||||
Host::OSD_WARNING_DURATION);
|
||||
config.UpscaleMultiplier = static_cast<float>(max_upscale_multiplier);
|
||||
}
|
||||
|
||||
static bool OpenGSRenderer(GSRendererType renderer, u8* basemem)
|
||||
{
|
||||
// Must be done first, initialization routines in GSState use GSIsHardwareRenderer().
|
||||
|
@ -184,6 +204,7 @@ static bool OpenGSRenderer(GSRendererType renderer, u8* basemem)
|
|||
}
|
||||
else if (renderer != GSRendererType::SW)
|
||||
{
|
||||
GSClampUpscaleMultiplier(GSConfig);
|
||||
g_gs_renderer = std::make_unique<GSRendererHW>();
|
||||
}
|
||||
else
|
||||
|
@ -548,9 +569,9 @@ std::optional<float> GSGetHostRefreshRate()
|
|||
return surface_refresh_rate;
|
||||
}
|
||||
|
||||
void GSGetAdaptersAndFullscreenModes(
|
||||
GSRendererType renderer, std::vector<std::string>* adapters, std::vector<std::string>* fullscreen_modes)
|
||||
std::vector<GSAdapterInfo> GSGetAdapterInfo(GSRendererType renderer)
|
||||
{
|
||||
std::vector<GSAdapterInfo> ret;
|
||||
switch (renderer)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
@ -559,12 +580,7 @@ void GSGetAdaptersAndFullscreenModes(
|
|||
{
|
||||
auto factory = D3D::CreateFactory(false);
|
||||
if (factory)
|
||||
{
|
||||
if (adapters)
|
||||
*adapters = D3D::GetAdapterNames(factory.get());
|
||||
if (fullscreen_modes)
|
||||
*fullscreen_modes = D3D::GetFullscreenModes(factory.get(), EmuConfig.GS.Adapter);
|
||||
}
|
||||
ret = D3D::GetAdapterInfo(factory.get());
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
@ -572,7 +588,7 @@ void GSGetAdaptersAndFullscreenModes(
|
|||
#ifdef ENABLE_VULKAN
|
||||
case GSRendererType::VK:
|
||||
{
|
||||
GSDeviceVK::GetAdaptersAndFullscreenModes(adapters, fullscreen_modes);
|
||||
ret = GSDeviceVK::GetAdapterInfo();
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
@ -580,8 +596,7 @@ void GSGetAdaptersAndFullscreenModes(
|
|||
#ifdef __APPLE__
|
||||
case GSRendererType::Metal:
|
||||
{
|
||||
if (adapters)
|
||||
*adapters = GetMetalAdapterList();
|
||||
ret = GetMetalAdapterList();
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
@ -589,6 +604,14 @@ void GSGetAdaptersAndFullscreenModes(
|
|||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
u32 GSGetMaxUpscaleMultiplier(u32 max_texture_size)
|
||||
{
|
||||
// Maximum GS target size is 1280x1280. Assume we want to upscale the max size target.
|
||||
return std::max(max_texture_size / 1280, 1u);
|
||||
}
|
||||
|
||||
GSVideoMode GSgetDisplayMode()
|
||||
|
@ -712,6 +735,9 @@ void GSUpdateConfig(const Pcsx2Config::GSOptions& new_config)
|
|||
return;
|
||||
}
|
||||
|
||||
// Ensure upscale multiplier is in range.
|
||||
GSClampUpscaleMultiplier(GSConfig);
|
||||
|
||||
// Options which aren't using the global struct yet, so we need to recreate all GS objects.
|
||||
if (GSConfig.SWExtraThreads != old_config.SWExtraThreads ||
|
||||
GSConfig.SWExtraThreadsHeight != old_config.SWExtraThreadsHeight)
|
||||
|
|
|
@ -41,6 +41,14 @@ enum class GSDisplayAlignment
|
|||
RightOrBottom
|
||||
};
|
||||
|
||||
struct GSAdapterInfo
|
||||
{
|
||||
std::string name;
|
||||
std::vector<std::string> fullscreen_modes;
|
||||
u32 max_texture_size;
|
||||
u32 max_upscale_multiplier;
|
||||
};
|
||||
|
||||
class SmallStringBase;
|
||||
|
||||
// Returns the ID for the specified function, otherwise -1.
|
||||
|
@ -83,8 +91,8 @@ GSRendererType GSGetCurrentRenderer();
|
|||
bool GSIsHardwareRenderer();
|
||||
bool GSWantsExclusiveFullscreen();
|
||||
std::optional<float> GSGetHostRefreshRate();
|
||||
void GSGetAdaptersAndFullscreenModes(
|
||||
GSRendererType renderer, std::vector<std::string>* adapters, std::vector<std::string>* fullscreen_modes);
|
||||
std::vector<GSAdapterInfo> GSGetAdapterInfo(GSRendererType renderer);
|
||||
u32 GSGetMaxUpscaleMultiplier(u32 max_texture_size);
|
||||
GSVideoMode GSgetDisplayMode();
|
||||
void GSgetInternalResolution(int* width, int* height);
|
||||
void GSgetStats(SmallStringBase& info);
|
||||
|
|
|
@ -435,7 +435,8 @@ void GSDevice::TextureRecycleDeleter::operator()(GSTexture* const tex)
|
|||
|
||||
GSTexture* GSDevice::FetchSurface(GSTexture::Type type, int width, int height, int levels, GSTexture::Format format, bool clear, bool prefer_unused_texture)
|
||||
{
|
||||
const GSVector2i size(width, height);
|
||||
const GSVector2i size(std::clamp(width, 1, static_cast<int>(g_gs_device->GetMaxTextureSize())),
|
||||
std::clamp(height, 1, static_cast<int>(g_gs_device->GetMaxTextureSize())));
|
||||
FastList<GSTexture*>& pool = m_pool[type != GSTexture::Type::Texture];
|
||||
|
||||
GSTexture* t = nullptr;
|
||||
|
@ -475,14 +476,14 @@ GSTexture* GSDevice::FetchSurface(GSTexture::Type type, int width, int height, i
|
|||
}
|
||||
else
|
||||
{
|
||||
t = CreateSurface(type, width, height, levels, format);
|
||||
t = CreateSurface(type, size.x, size.y, levels, format);
|
||||
if (!t)
|
||||
{
|
||||
Console.Error("GS: Memory allocation failure for %dx%d texture. Purging pool and retrying.", width, height);
|
||||
ERROR_LOG("GS: Memory allocation failure for {}x{} texture. Purging pool and retrying.", size.x, size.y);
|
||||
PurgePool();
|
||||
if (!t)
|
||||
{
|
||||
Console.Error("GS: Memory allocation failure for %dx%d texture after purging pool.", width, height);
|
||||
ERROR_LOG("GS: Memory allocation failure for {}x{} texture after purging pool.", size.x, size.y);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -804,6 +804,7 @@ public:
|
|||
|
||||
protected:
|
||||
FeatureSupport m_features;
|
||||
u32 m_max_texture_size = 0;
|
||||
|
||||
struct
|
||||
{
|
||||
|
@ -888,6 +889,7 @@ public:
|
|||
__fi u64 GetPoolMemoryUsage() const { return m_pool_memory_usage; }
|
||||
|
||||
__fi FeatureSupport Features() const { return m_features; }
|
||||
__fi u32 GetMaxTextureSize() const { return m_max_texture_size; }
|
||||
|
||||
__fi const WindowInfo& GetWindowInfo() const { return m_window_info; }
|
||||
__fi s32 GetWindowWidth() const { return static_cast<s32>(m_window_info.surface_width); }
|
||||
|
|
|
@ -42,10 +42,10 @@ wil::com_ptr_nothrow<IDXGIFactory5> D3D::CreateFactory(bool debug)
|
|||
return factory;
|
||||
}
|
||||
|
||||
static std::string FixupDuplicateAdapterNames(const std::vector<std::string>& adapter_names, std::string adapter_name)
|
||||
static std::string FixupDuplicateAdapterNames(const std::vector<GSAdapterInfo>& adapters, std::string adapter_name)
|
||||
{
|
||||
if (std::any_of(adapter_names.begin(), adapter_names.end(),
|
||||
[&adapter_name](const std::string& other) { return (adapter_name == other); }))
|
||||
if (std::any_of(adapters.begin(), adapters.end(),
|
||||
[&adapter_name](const GSAdapterInfo& other) { return (adapter_name == other.name); }))
|
||||
{
|
||||
std::string original_adapter_name = std::move(adapter_name);
|
||||
|
||||
|
@ -54,73 +54,72 @@ static std::string FixupDuplicateAdapterNames(const std::vector<std::string>& ad
|
|||
{
|
||||
adapter_name = fmt::format("{} ({})", original_adapter_name.c_str(), current_extra);
|
||||
current_extra++;
|
||||
} while (std::any_of(adapter_names.begin(), adapter_names.end(),
|
||||
[&adapter_name](const std::string& other) { return (adapter_name == other); }));
|
||||
} while (std::any_of(adapters.begin(), adapters.end(),
|
||||
[&adapter_name](const GSAdapterInfo& other) { return (adapter_name == other.name); }));
|
||||
}
|
||||
|
||||
return adapter_name;
|
||||
}
|
||||
|
||||
std::vector<std::string> D3D::GetAdapterNames(IDXGIFactory5* factory)
|
||||
std::vector<GSAdapterInfo> D3D::GetAdapterInfo(IDXGIFactory5* factory)
|
||||
{
|
||||
std::vector<std::string> adapter_names;
|
||||
std::vector<GSAdapterInfo> adapters;
|
||||
|
||||
wil::com_ptr_nothrow<IDXGIAdapter1> adapter;
|
||||
for (u32 index = 0;; index++)
|
||||
{
|
||||
const HRESULT hr = factory->EnumAdapters1(index, adapter.put());
|
||||
HRESULT hr = factory->EnumAdapters1(index, adapter.put());
|
||||
if (hr == DXGI_ERROR_NOT_FOUND)
|
||||
break;
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
Console.Error(fmt::format("IDXGIFactory2::EnumAdapters() returned %08X", hr));
|
||||
ERROR_LOG("IDXGIFactory2::EnumAdapters() returned {:08X}", static_cast<unsigned>(hr));
|
||||
continue;
|
||||
}
|
||||
|
||||
adapter_names.push_back(FixupDuplicateAdapterNames(adapter_names, GetAdapterName(adapter.get())));
|
||||
GSAdapterInfo ai;
|
||||
ai.name = FixupDuplicateAdapterNames(adapters, GetAdapterName(adapter.get()));
|
||||
|
||||
// Unfortunately we can't get any properties such as feature level without creating the device.
|
||||
// So just assume a max of the D3D11 max across the board.
|
||||
ai.max_texture_size = D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
|
||||
ai.max_upscale_multiplier = GSGetMaxUpscaleMultiplier(ai.max_texture_size);
|
||||
|
||||
wil::com_ptr_nothrow<IDXGIOutput> output;
|
||||
if (SUCCEEDED(hr = adapter->EnumOutputs(0, &output)))
|
||||
{
|
||||
UINT num_modes = 0;
|
||||
if (SUCCEEDED(hr = output->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, 0, &num_modes, nullptr)))
|
||||
{
|
||||
std::vector<DXGI_MODE_DESC> dmodes(num_modes);
|
||||
if (SUCCEEDED(hr = output->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, 0, &num_modes, dmodes.data())))
|
||||
{
|
||||
for (const DXGI_MODE_DESC& mode : dmodes)
|
||||
{
|
||||
ai.fullscreen_modes.push_back(GSDevice::GetFullscreenModeString(mode.Width, mode.Height,
|
||||
static_cast<float>(mode.RefreshRate.Numerator) / static_cast<float>(mode.RefreshRate.Denominator)));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_LOG("GetDisplayModeList() (2) failed: {:08X}", static_cast<unsigned>(hr));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_LOG("GetDisplayModeList() failed: {:08X}", static_cast<unsigned>(hr));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_LOG("EnumOutputs() failed: {:08X}", static_cast<unsigned>(hr));
|
||||
}
|
||||
|
||||
adapters.push_back(std::move(ai));
|
||||
}
|
||||
|
||||
return adapter_names;
|
||||
}
|
||||
|
||||
std::vector<std::string> D3D::GetFullscreenModes(IDXGIFactory5* factory, const std::string_view adapter_name)
|
||||
{
|
||||
std::vector<std::string> modes;
|
||||
HRESULT hr;
|
||||
|
||||
wil::com_ptr_nothrow<IDXGIAdapter1> adapter = GetChosenOrFirstAdapter(factory, adapter_name);
|
||||
if (!adapter)
|
||||
return modes;
|
||||
|
||||
wil::com_ptr_nothrow<IDXGIOutput> output;
|
||||
if (FAILED(hr = adapter->EnumOutputs(0, &output)))
|
||||
{
|
||||
Console.Error("EnumOutputs() failed: %08X", hr);
|
||||
return modes;
|
||||
}
|
||||
|
||||
UINT num_modes = 0;
|
||||
if (FAILED(hr = output->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, 0, &num_modes, nullptr)))
|
||||
{
|
||||
Console.Error("GetDisplayModeList() failed: %08X", hr);
|
||||
return modes;
|
||||
}
|
||||
|
||||
std::vector<DXGI_MODE_DESC> dmodes(num_modes);
|
||||
if (FAILED(hr = output->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, 0, &num_modes, dmodes.data())))
|
||||
{
|
||||
Console.Error("GetDisplayModeList() (2) failed: %08X", hr);
|
||||
return modes;
|
||||
}
|
||||
|
||||
for (const DXGI_MODE_DESC& mode : dmodes)
|
||||
{
|
||||
modes.push_back(GSDevice::GetFullscreenModeString(mode.Width, mode.Height,
|
||||
static_cast<float>(mode.RefreshRate.Numerator) / static_cast<float>(mode.RefreshRate.Denominator)));
|
||||
}
|
||||
|
||||
return modes;
|
||||
return adapters;
|
||||
}
|
||||
|
||||
bool D3D::GetRequestedExclusiveFullscreenModeDesc(IDXGIFactory5* factory, const RECT& window_rect, u32 width,
|
||||
|
@ -187,7 +186,7 @@ bool D3D::GetRequestedExclusiveFullscreenModeDesc(IDXGIFactory5* factory, const
|
|||
if (FAILED(hr = intersecting_output->FindClosestMatchingMode(&request_mode, fullscreen_mode, nullptr)) ||
|
||||
request_mode.Format != format)
|
||||
{
|
||||
Console.Error("Failed to find closest matching mode, hr=%08X", hr);
|
||||
ERROR_LOG("Failed to find closest matching mode, hr={:08X}", static_cast<unsigned>(hr));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -203,7 +202,7 @@ wil::com_ptr_nothrow<IDXGIAdapter1> D3D::GetAdapterByName(IDXGIFactory5* factory
|
|||
|
||||
// This might seem a bit odd to cache the names.. but there's a method to the madness.
|
||||
// We might have two GPUs with the same name... :)
|
||||
std::vector<std::string> adapter_names;
|
||||
std::vector<GSAdapterInfo> adapter_names;
|
||||
|
||||
wil::com_ptr_nothrow<IDXGIAdapter1> adapter;
|
||||
for (u32 index = 0;; index++)
|
||||
|
@ -214,18 +213,19 @@ wil::com_ptr_nothrow<IDXGIAdapter1> D3D::GetAdapterByName(IDXGIFactory5* factory
|
|||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
Console.Error(fmt::format("IDXGIFactory2::EnumAdapters() returned %08X", hr));
|
||||
ERROR_LOG("IDXGIFactory2::EnumAdapters() returned {:08X}", static_cast<unsigned>(hr));
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string adapter_name = FixupDuplicateAdapterNames(adapter_names, GetAdapterName(adapter.get()));
|
||||
if (adapter_name == name)
|
||||
GSAdapterInfo ai;
|
||||
ai.name = FixupDuplicateAdapterNames(adapter_names, GetAdapterName(adapter.get()));
|
||||
if (ai.name == name)
|
||||
{
|
||||
Console.WriteLn(fmt::format("D3D: Found adapter '{}'", adapter_name));
|
||||
INFO_LOG("D3D: Found adapter '{}'", ai.name);
|
||||
return adapter;
|
||||
}
|
||||
|
||||
adapter_names.push_back(std::move(adapter_name));
|
||||
adapter_names.push_back(std::move(ai));
|
||||
}
|
||||
|
||||
Console.Warning(fmt::format("Adapter '{}' not found.", name));
|
||||
|
@ -404,9 +404,7 @@ GSRendererType D3D::GetPreferredRenderer()
|
|||
if (check_for_mapping_layers())
|
||||
return false;
|
||||
|
||||
std::vector<std::string> vk_adapter_names;
|
||||
GSDeviceVK::GetAdaptersAndFullscreenModes(&vk_adapter_names, nullptr);
|
||||
if (!vk_adapter_names.empty())
|
||||
if (!GSDeviceVK::EnumerateGPUs().empty())
|
||||
return true;
|
||||
|
||||
Host::AddIconOSDMessage("VKDriverUnsupported", ICON_FA_TV, TRANSLATE_STR("GS",
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
#include "common/RedtapeWindows.h"
|
||||
#include "common/RedtapeWilCom.h"
|
||||
|
||||
#include "pcsx2/Config.h"
|
||||
#include "Config.h"
|
||||
#include "GS/GS.h"
|
||||
|
||||
#include <d3d11_1.h>
|
||||
#include <dxgi1_5.h>
|
||||
|
@ -19,11 +20,8 @@ namespace D3D
|
|||
// create a dxgi factory
|
||||
wil::com_ptr_nothrow<IDXGIFactory5> CreateFactory(bool debug);
|
||||
|
||||
// returns a list of all adapter names
|
||||
std::vector<std::string> GetAdapterNames(IDXGIFactory5* factory);
|
||||
|
||||
// returns a list of fullscreen modes for the specified adapter
|
||||
std::vector<std::string> GetFullscreenModes(IDXGIFactory5* factory, const std::string_view adapter_name);
|
||||
// returns a list of all adapter information
|
||||
std::vector<GSAdapterInfo> GetAdapterInfo(IDXGIFactory5* factory);
|
||||
|
||||
// returns the fullscreen mode to use for the specified dimensions
|
||||
bool GetRequestedExclusiveFullscreenModeDesc(IDXGIFactory5* factory, const RECT& window_rect, u32 width, u32 height,
|
||||
|
|
|
@ -595,13 +595,10 @@ void GSDevice11::SetFeatures(IDXGIAdapter1* adapter)
|
|||
m_features.vs_expand = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int GSDevice11::GetMaxTextureSize() const
|
||||
{
|
||||
return (m_feature_level >= D3D_FEATURE_LEVEL_11_0) ?
|
||||
D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION :
|
||||
D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
|
||||
m_max_texture_size = (m_feature_level >= D3D_FEATURE_LEVEL_11_0) ?
|
||||
D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION :
|
||||
D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION;
|
||||
}
|
||||
|
||||
bool GSDevice11::HasSurface() const
|
||||
|
@ -1185,10 +1182,8 @@ void GSDevice11::InsertDebugMessage(DebugMessageCategory category, const char* f
|
|||
GSTexture* GSDevice11::CreateSurface(GSTexture::Type type, int width, int height, int levels, GSTexture::Format format)
|
||||
{
|
||||
D3D11_TEXTURE2D_DESC desc = {};
|
||||
|
||||
// Texture limit for D3D10/11 min 1, max 8192 D3D10, max 16384 D3D11.
|
||||
desc.Width = std::clamp(width, 1, GetMaxTextureSize());
|
||||
desc.Height = std::clamp(height, 1, GetMaxTextureSize());
|
||||
desc.Width = width;
|
||||
desc.Height = height;
|
||||
desc.Format = GSTexture11::GetDXGIFormat(format);
|
||||
desc.MipLevels = levels;
|
||||
desc.ArraySize = 1;
|
||||
|
|
|
@ -91,7 +91,6 @@ private:
|
|||
};
|
||||
|
||||
void SetFeatures(IDXGIAdapter1* adapter);
|
||||
int GetMaxTextureSize() const;
|
||||
|
||||
u32 GetSwapChainBufferCount() const;
|
||||
bool CreateSwapChain();
|
||||
|
|
|
@ -1227,6 +1227,8 @@ bool GSDevice12::CheckFeatures()
|
|||
SupportsTextureFormat(DXGI_FORMAT_BC3_UNORM);
|
||||
m_features.bptc_textures = SupportsTextureFormat(DXGI_FORMAT_BC7_UNORM);
|
||||
|
||||
m_max_texture_size = D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION;
|
||||
|
||||
BOOL allow_tearing_supported = false;
|
||||
HRESULT hr = m_dxgi_factory->CheckFeatureSupport(
|
||||
DXGI_FEATURE_PRESENT_ALLOW_TEARING, &allow_tearing_supported, sizeof(allow_tearing_supported));
|
||||
|
@ -1289,22 +1291,19 @@ void GSDevice12::LookupNativeFormat(GSTexture::Format format, DXGI_FORMAT* d3d_f
|
|||
|
||||
GSTexture* GSDevice12::CreateSurface(GSTexture::Type type, int width, int height, int levels, GSTexture::Format format)
|
||||
{
|
||||
const u32 clamped_width = static_cast<u32>(std::clamp<int>(width, 1, D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION));
|
||||
const u32 clamped_height = static_cast<u32>(std::clamp<int>(height, 1, D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION));
|
||||
|
||||
DXGI_FORMAT dxgi_format, srv_format, rtv_format, dsv_format;
|
||||
LookupNativeFormat(format, &dxgi_format, &srv_format, &rtv_format, &dsv_format);
|
||||
|
||||
const DXGI_FORMAT uav_format = (type == GSTexture::Type::RWTexture) ? dxgi_format : DXGI_FORMAT_UNKNOWN;
|
||||
|
||||
std::unique_ptr<GSTexture12> tex(GSTexture12::Create(type, format, clamped_width, clamped_height, levels,
|
||||
std::unique_ptr<GSTexture12> tex(GSTexture12::Create(type, format, width, height, levels,
|
||||
dxgi_format, srv_format, rtv_format, dsv_format, uav_format));
|
||||
if (!tex)
|
||||
{
|
||||
// We're probably out of vram, try flushing the command buffer to release pending textures.
|
||||
PurgePool();
|
||||
ExecuteCommandListAndRestartRenderPass(true, "Couldn't allocate texture.");
|
||||
tex = GSTexture12::Create(type, format, clamped_width, clamped_height, levels, dxgi_format, srv_format,
|
||||
tex = GSTexture12::Create(type, format, width, height, levels, dxgi_format, srv_format,
|
||||
rtv_format, dsv_format, uav_format);
|
||||
}
|
||||
|
||||
|
|
|
@ -25,12 +25,25 @@ GSDevice* MakeGSDeviceMTL()
|
|||
return new GSDeviceMTL();
|
||||
}
|
||||
|
||||
std::vector<std::string> GetMetalAdapterList()
|
||||
std::vector<GSAdapterInfo> GetMetalAdapterList()
|
||||
{ @autoreleasepool {
|
||||
std::vector<std::string> list;
|
||||
std::vector<GSAdapterInfo> list;
|
||||
auto devs = MRCTransfer(MTLCopyAllDevices());
|
||||
for (id<MTLDevice> dev in devs.Get())
|
||||
list.push_back([[dev name] UTF8String]);
|
||||
{
|
||||
GSAdapterInfo ai;
|
||||
ai.name = [[dev name] UTF8String];
|
||||
|
||||
ai.max_texture_size = 8192;
|
||||
if ([dev supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily1_v1])
|
||||
ai.max_texture_size = 16384;
|
||||
if (@available(macOS 10.15, iOS 13.0, *))
|
||||
if ([dev supportsFamily:MTLGPUFamilyApple3])
|
||||
ai.max_texture_size = 16384;
|
||||
|
||||
ai.max_upscale_multiplier = GSGetMaxUpscaleMultiplier(ai.max_texture_size);
|
||||
list.push_back(std::move(ai));
|
||||
}
|
||||
return list;
|
||||
}}
|
||||
|
||||
|
@ -507,8 +520,8 @@ GSTexture* GSDeviceMTL::CreateSurface(GSTexture::Type type, int width, int heigh
|
|||
|
||||
MTLTextureDescriptor* desc = [MTLTextureDescriptor
|
||||
texture2DDescriptorWithPixelFormat:fmt
|
||||
width:std::max(1, std::min(width, m_dev.features.max_texsize))
|
||||
height:std::max(1, std::min(height, m_dev.features.max_texsize))
|
||||
width:width
|
||||
height:height
|
||||
mipmapped:levels > 1];
|
||||
|
||||
if (levels > 1)
|
||||
|
@ -905,6 +918,7 @@ bool GSDeviceMTL::Create(GSVSyncMode vsync_mode, bool allow_present_throttle)
|
|||
m_features.stencil_buffer = true;
|
||||
m_features.cas_sharpening = true;
|
||||
m_features.test_and_sample_depth = true;
|
||||
m_max_texture_size = m_dev.features.max_texsize;
|
||||
|
||||
// Init metal stuff
|
||||
m_fn_constants = MRCTransfer([MTLFunctionConstantValues new]);
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "GS/GS.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
@ -12,6 +14,6 @@
|
|||
|
||||
class GSDevice;
|
||||
GSDevice* MakeGSDeviceMTL();
|
||||
std::vector<std::string> GetMetalAdapterList();
|
||||
std::vector<GSAdapterInfo> GetMetalAdapterList();
|
||||
|
||||
#endif
|
||||
|
|
|
@ -767,6 +767,10 @@ bool GSDeviceOGL::CheckFeatures(bool& buggy_pbo)
|
|||
(point_range[0] <= GSConfig.UpscaleMultiplier && point_range[1] >= GSConfig.UpscaleMultiplier);
|
||||
m_features.line_expand = false;
|
||||
|
||||
GLint max_texture_size = 1024;
|
||||
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
|
||||
m_max_texture_size = std::max(1024u, static_cast<u32>(max_texture_size));
|
||||
|
||||
Console.WriteLn("Using %s for point expansion, %s for line expansion and %s for sprite expansion.",
|
||||
m_features.point_expand ? "hardware" : (m_features.vs_expand ? "vertex expanding" : "UNSUPPORTED"),
|
||||
m_features.line_expand ? "hardware" : (m_features.vs_expand ? "vertex expanding" : "UNSUPPORTED"),
|
||||
|
|
|
@ -291,24 +291,58 @@ GSDeviceVK::GPUList GSDeviceVK::EnumerateGPUs(VkInstance instance)
|
|||
if (has_missing_extension)
|
||||
continue;
|
||||
|
||||
std::string gpu_name = props.deviceName;
|
||||
GSAdapterInfo ai;
|
||||
ai.name = props.deviceName;
|
||||
ai.max_texture_size = std::min(props.limits.maxFramebufferWidth, props.limits.maxImageDimension2D);
|
||||
ai.max_upscale_multiplier = GSGetMaxUpscaleMultiplier(ai.max_texture_size);
|
||||
|
||||
// handle duplicate adapter names
|
||||
if (std::any_of(
|
||||
gpus.begin(), gpus.end(), [&gpu_name](const auto& other) { return (gpu_name == other.second); }))
|
||||
gpus.begin(), gpus.end(), [&ai](const auto& other) { return (ai.name == other.second.name); }))
|
||||
{
|
||||
std::string original_adapter_name = std::move(gpu_name);
|
||||
std::string original_adapter_name = std::move(ai.name);
|
||||
|
||||
u32 current_extra = 2;
|
||||
do
|
||||
{
|
||||
gpu_name = fmt::format("{} ({})", original_adapter_name, current_extra);
|
||||
ai.name = fmt::format("{} ({})", original_adapter_name, current_extra);
|
||||
current_extra++;
|
||||
} while (std::any_of(
|
||||
gpus.begin(), gpus.end(), [&gpu_name](const auto& other) { return (gpu_name == other.second); }));
|
||||
gpus.begin(), gpus.end(), [&ai](const auto& other) { return (ai.name == other.second.name); }));
|
||||
}
|
||||
|
||||
gpus.emplace_back(device, std::move(gpu_name));
|
||||
gpus.emplace_back(device, std::move(ai));
|
||||
}
|
||||
|
||||
return gpus;
|
||||
}
|
||||
|
||||
GSDeviceVK::GPUList GSDeviceVK::EnumerateGPUs()
|
||||
{
|
||||
std::unique_lock lock(s_instance_mutex);
|
||||
|
||||
// Device shouldn't be torn down since we have the lock.
|
||||
GPUList gpus;
|
||||
if (g_gs_device && Vulkan::IsVulkanLibraryLoaded())
|
||||
{
|
||||
gpus = EnumerateGPUs(GSDeviceVK::GetInstance()->GetVulkanInstance());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Vulkan::LoadVulkanLibrary(nullptr))
|
||||
{
|
||||
OptionalExtensions oe = {};
|
||||
const VkInstance instance = CreateVulkanInstance(WindowInfo(), &oe, false, false);
|
||||
if (instance != VK_NULL_HANDLE)
|
||||
{
|
||||
if (Vulkan::LoadVulkanInstanceFunctions(instance))
|
||||
gpus = EnumerateGPUs(instance);
|
||||
|
||||
vkDestroyInstance(instance, nullptr);
|
||||
}
|
||||
|
||||
Vulkan::UnloadVulkanLibrary();
|
||||
}
|
||||
}
|
||||
|
||||
return gpus;
|
||||
|
@ -1928,58 +1962,28 @@ bool GSDeviceVK::AllocatePreinitializedGPUBuffer(u32 size, VkBuffer* gpu_buffer,
|
|||
}
|
||||
|
||||
|
||||
void GSDeviceVK::GPUListToAdapterNames(std::vector<std::string>* dest, VkInstance instance)
|
||||
std::vector<GSAdapterInfo> GSDeviceVK::GetAdapterInfo()
|
||||
{
|
||||
GPUList gpus = EnumerateGPUs(instance);
|
||||
dest->clear();
|
||||
dest->reserve(gpus.size());
|
||||
for (auto& [gpu, name] : gpus)
|
||||
dest->push_back(std::move(name));
|
||||
}
|
||||
|
||||
void GSDeviceVK::GetAdaptersAndFullscreenModes(
|
||||
std::vector<std::string>* adapters, std::vector<std::string>* fullscreen_modes)
|
||||
{
|
||||
std::unique_lock lock(s_instance_mutex);
|
||||
|
||||
// Device shouldn't be torn down since we have the lock.
|
||||
if (g_gs_device && Vulkan::IsVulkanLibraryLoaded())
|
||||
{
|
||||
if (adapters)
|
||||
GPUListToAdapterNames(adapters, GSDeviceVK::GetInstance()->GetVulkanInstance());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Vulkan::LoadVulkanLibrary(nullptr))
|
||||
{
|
||||
OptionalExtensions oe = {};
|
||||
const VkInstance instance = CreateVulkanInstance(WindowInfo(), &oe, false, false);
|
||||
if (instance != VK_NULL_HANDLE)
|
||||
{
|
||||
if (Vulkan::LoadVulkanInstanceFunctions(instance))
|
||||
GPUListToAdapterNames(adapters, instance);
|
||||
|
||||
vkDestroyInstance(instance, nullptr);
|
||||
}
|
||||
|
||||
Vulkan::UnloadVulkanLibrary();
|
||||
}
|
||||
}
|
||||
GPUList gpus = EnumerateGPUs();
|
||||
std::vector<GSAdapterInfo> ret;
|
||||
ret.reserve(gpus.size());
|
||||
for (auto& [physical_device, ai] : gpus)
|
||||
ret.push_back(std::move(ai));
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool GSDeviceVK::IsSuitableDefaultRenderer()
|
||||
{
|
||||
std::vector<std::string> adapters;
|
||||
GetAdaptersAndFullscreenModes(&adapters, nullptr);
|
||||
if (adapters.empty())
|
||||
GPUList gpus = EnumerateGPUs();
|
||||
if (gpus.empty())
|
||||
{
|
||||
// No adapters, not gonna be able to use VK.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check the first GPU, should be enough.
|
||||
const std::string& name = adapters.front();
|
||||
Console.WriteLn(fmt::format("Using Vulkan GPU '{}' for automatic renderer check.", name));
|
||||
const std::string& name = gpus.front().second.name;
|
||||
INFO_LOG("Using Vulkan GPU '{}' for automatic renderer check.", name);
|
||||
|
||||
// Any software rendering (LLVMpipe, SwiftShader).
|
||||
if (StringUtil::StartsWithNoCase(name, "llvmpipe") || StringUtil::StartsWithNoCase(name, "SwiftShader"))
|
||||
|
@ -2451,18 +2455,17 @@ bool GSDeviceVK::CreateDeviceAndSwapChain()
|
|||
m_instance = CreateVulkanInstance(m_window_info, &m_optional_extensions, enable_debug_utils, enable_validation_layer);
|
||||
if (m_instance == VK_NULL_HANDLE)
|
||||
{
|
||||
Host::ReportErrorAsync(
|
||||
"Error", "Failed to create Vulkan instance. Does your GPU and/or driver support Vulkan?");
|
||||
Host::ReportErrorAsync("Error", "Failed to create Vulkan instance. Does your GPU and/or driver support Vulkan?");
|
||||
return false;
|
||||
}
|
||||
|
||||
Console.Error("Vulkan validation/debug layers requested but are unavailable. Creating non-debug device.");
|
||||
ERROR_LOG("Vulkan validation/debug layers requested but are unavailable. Creating non-debug device.");
|
||||
}
|
||||
}
|
||||
|
||||
if (!Vulkan::LoadVulkanInstanceFunctions(m_instance))
|
||||
{
|
||||
Console.Error("Failed to load Vulkan instance functions");
|
||||
ERROR_LOG("Failed to load Vulkan instance functions");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2478,8 +2481,8 @@ bool GSDeviceVK::CreateDeviceAndSwapChain()
|
|||
u32 gpu_index = 0;
|
||||
for (; gpu_index < static_cast<u32>(gpus.size()); gpu_index++)
|
||||
{
|
||||
Console.WriteLn(fmt::format("GPU {}: {}", gpu_index, gpus[gpu_index].second));
|
||||
if (gpus[gpu_index].second == GSConfig.Adapter)
|
||||
DEV_LOG("GPU {}: {}", gpu_index, gpus[gpu_index].second.name);
|
||||
if (gpus[gpu_index].second.name == GSConfig.Adapter)
|
||||
{
|
||||
m_physical_device = gpus[gpu_index].first;
|
||||
break;
|
||||
|
@ -2488,14 +2491,13 @@ bool GSDeviceVK::CreateDeviceAndSwapChain()
|
|||
|
||||
if (gpu_index == static_cast<u32>(gpus.size()))
|
||||
{
|
||||
Console.Warning(
|
||||
fmt::format("Requested GPU '{}' not found, using first ({})", GSConfig.Adapter, gpus[0].second));
|
||||
WARNING_LOG("Requested GPU '{}' not found, using first ({})", GSConfig.Adapter, gpus[0].second.name);
|
||||
m_physical_device = gpus[0].first;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLn(fmt::format("No GPU requested, using first ({})", gpus[0].second));
|
||||
INFO_LOG("No GPU requested, using first ({})", gpus[0].second.name);
|
||||
m_physical_device = gpus[0].first;
|
||||
}
|
||||
|
||||
|
@ -2647,6 +2649,8 @@ bool GSDeviceVK::CheckFeatures()
|
|||
Host::OSD_WARNING_DURATION);
|
||||
}
|
||||
|
||||
m_max_texture_size = m_device_properties.limits.maxImageDimension2D;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2693,18 +2697,13 @@ VkFormat GSDeviceVK::LookupNativeFormat(GSTexture::Format format) const
|
|||
|
||||
GSTexture* GSDeviceVK::CreateSurface(GSTexture::Type type, int width, int height, int levels, GSTexture::Format format)
|
||||
{
|
||||
const u32 clamped_width =
|
||||
static_cast<u32>(std::clamp<int>(width, 1, m_device_properties.limits.maxImageDimension2D));
|
||||
const u32 clamped_height =
|
||||
static_cast<u32>(std::clamp<int>(height, 1, m_device_properties.limits.maxImageDimension2D));
|
||||
|
||||
std::unique_ptr<GSTexture> tex(GSTextureVK::Create(type, format, clamped_width, clamped_height, levels));
|
||||
std::unique_ptr<GSTexture> tex = GSTextureVK::Create(type, format, width, height, levels);
|
||||
if (!tex)
|
||||
{
|
||||
// We're probably out of vram, try flushing the command buffer to release pending textures.
|
||||
PurgePool();
|
||||
ExecuteCommandBufferAndRestartRenderPass(true, "Couldn't allocate texture.");
|
||||
tex = GSTextureVK::Create(type, format, clamped_width, clamped_height, levels);
|
||||
tex = GSTextureVK::Create(type, format, width, height, levels);
|
||||
}
|
||||
|
||||
return tex.release();
|
||||
|
|
|
@ -129,11 +129,6 @@ private:
|
|||
static VkInstance CreateVulkanInstance(const WindowInfo& wi, OptionalExtensions* oe, bool enable_debug_utils,
|
||||
bool enable_validation_layer);
|
||||
|
||||
// Returns a list of Vulkan-compatible GPUs.
|
||||
using GPUList = std::vector<std::pair<VkPhysicalDevice, std::string>>;
|
||||
static GPUList EnumerateGPUs(VkInstance instance);
|
||||
static void GPUListToAdapterNames(std::vector<std::string>* dest, VkInstance instance);
|
||||
|
||||
// Enable/disable debug message runtime.
|
||||
bool EnableDebugUtils();
|
||||
void DisableDebugUtils();
|
||||
|
@ -474,8 +469,11 @@ public:
|
|||
|
||||
__fi static GSDeviceVK* GetInstance() { return static_cast<GSDeviceVK*>(g_gs_device.get()); }
|
||||
|
||||
static void GetAdaptersAndFullscreenModes(
|
||||
std::vector<std::string>* adapters, std::vector<std::string>* fullscreen_modes);
|
||||
// Returns a list of Vulkan-compatible GPUs.
|
||||
using GPUList = std::vector<std::pair<VkPhysicalDevice, GSAdapterInfo>>;
|
||||
static GPUList EnumerateGPUs();
|
||||
static GPUList EnumerateGPUs(VkInstance instance);
|
||||
static std::vector<GSAdapterInfo> GetAdapterInfo();
|
||||
|
||||
/// Returns true if Vulkan is suitable as a default for the devices in the system.
|
||||
static bool IsSuitableDefaultRenderer();
|
||||
|
|
|
@ -402,8 +402,7 @@ namespace FullscreenUI
|
|||
static std::unique_ptr<INISettingsInterface> s_game_settings_interface;
|
||||
static std::unique_ptr<GameList::Entry> s_game_settings_entry;
|
||||
static std::vector<std::pair<std::string, bool>> s_game_list_directories_cache;
|
||||
static std::vector<std::string> s_graphics_adapter_list_cache;
|
||||
static std::vector<std::string> s_fullscreen_mode_list_cache;
|
||||
static std::vector<GSAdapterInfo> s_graphics_adapter_list_cache;
|
||||
static Patch::PatchInfoList s_game_patch_list;
|
||||
static std::vector<std::string> s_enabled_game_patch_cache;
|
||||
static Patch::PatchInfoList s_game_cheats_list;
|
||||
|
@ -762,7 +761,6 @@ void FullscreenUI::Shutdown(bool clear_state)
|
|||
s_game_cheats_list = {};
|
||||
s_enabled_game_patch_cache = {};
|
||||
s_game_patch_list = {};
|
||||
s_fullscreen_mode_list_cache = {};
|
||||
s_graphics_adapter_list_cache = {};
|
||||
s_current_game_title = {};
|
||||
s_current_game_subtitle = {};
|
||||
|
@ -2736,7 +2734,7 @@ void FullscreenUI::SwitchToGameSettings(const GameList::Entry* entry)
|
|||
|
||||
void FullscreenUI::PopulateGraphicsAdapterList()
|
||||
{
|
||||
GSGetAdaptersAndFullscreenModes(GSConfig.Renderer, &s_graphics_adapter_list_cache, &s_fullscreen_mode_list_cache);
|
||||
s_graphics_adapter_list_cache = GSGetAdapterInfo(GSConfig.Renderer);
|
||||
}
|
||||
|
||||
void FullscreenUI::PopulateGameListDirectoryCache(SettingsInterface* si)
|
||||
|
|
|
@ -883,9 +883,6 @@ void Pcsx2Config::GSOptions::LoadSave(SettingsWrapper& wrap)
|
|||
SettingsWrapIntEnumEx(Renderer, "Renderer");
|
||||
SettingsWrapEntryEx(UpscaleMultiplier, "upscale_multiplier");
|
||||
|
||||
// ~51x would the upper bound here for 32768x32768 textures, but you'll run out VRAM long before then.
|
||||
UpscaleMultiplier = std::clamp(UpscaleMultiplier, 1.0f, 50.0f);
|
||||
|
||||
SettingsWrapBitBoolEx(HWMipmap, "hw_mipmap");
|
||||
SettingsWrapIntEnumEx(AccurateBlendingUnit, "accurate_blending_unit");
|
||||
SettingsWrapIntEnumEx(TextureFiltering, "filter");
|
||||
|
|
Loading…
Reference in New Issue