Merge pull request #11100 from Pokechu22/software-settings-merge
Use the same settings for the software renderer as other backends
This commit is contained in:
commit
0c19a1d87c
|
@ -115,8 +115,8 @@ bool SavePNG(const std::string& path, const u8* input, ImageByteFormat format, u
|
||||||
|
|
||||||
size_t image_len = 0;
|
size_t image_len = 0;
|
||||||
spng_decoded_image_size(ctx.get(), SPNG_FMT_PNG, &image_len);
|
spng_decoded_image_size(ctx.get(), SPNG_FMT_PNG, &image_len);
|
||||||
INFO_LOG_FMT(FRAMEDUMP, "{} byte {} by {} image saved to {} at level {} in {}", image_len, width,
|
INFO_LOG_FMT(FRAMEDUMP, "{} byte {} by {} image saved to {} at level {} in {} ms", image_len,
|
||||||
height, path, level, timer.ElapsedMs());
|
width, height, path, level, timer.ElapsedMs());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -96,8 +96,6 @@ const Info<bool> GFX_SW_DUMP_OBJECTS{{System::GFX, "Settings", "SWDumpObjects"},
|
||||||
const Info<bool> GFX_SW_DUMP_TEV_STAGES{{System::GFX, "Settings", "SWDumpTevStages"}, false};
|
const Info<bool> GFX_SW_DUMP_TEV_STAGES{{System::GFX, "Settings", "SWDumpTevStages"}, false};
|
||||||
const Info<bool> GFX_SW_DUMP_TEV_TEX_FETCHES{{System::GFX, "Settings", "SWDumpTevTexFetches"},
|
const Info<bool> GFX_SW_DUMP_TEV_TEX_FETCHES{{System::GFX, "Settings", "SWDumpTevTexFetches"},
|
||||||
false};
|
false};
|
||||||
const Info<int> GFX_SW_DRAW_START{{System::GFX, "Settings", "SWDrawStart"}, 0};
|
|
||||||
const Info<int> GFX_SW_DRAW_END{{System::GFX, "Settings", "SWDrawEnd"}, 100000};
|
|
||||||
|
|
||||||
const Info<bool> GFX_PREFER_GLES{{System::GFX, "Settings", "PreferGLES"}, false};
|
const Info<bool> GFX_PREFER_GLES{{System::GFX, "Settings", "PreferGLES"}, false};
|
||||||
|
|
||||||
|
|
|
@ -77,8 +77,6 @@ extern const Info<bool> GFX_SAVE_TEXTURE_CACHE_TO_STATE;
|
||||||
extern const Info<bool> GFX_SW_DUMP_OBJECTS;
|
extern const Info<bool> GFX_SW_DUMP_OBJECTS;
|
||||||
extern const Info<bool> GFX_SW_DUMP_TEV_STAGES;
|
extern const Info<bool> GFX_SW_DUMP_TEV_STAGES;
|
||||||
extern const Info<bool> GFX_SW_DUMP_TEV_TEX_FETCHES;
|
extern const Info<bool> GFX_SW_DUMP_TEV_TEX_FETCHES;
|
||||||
extern const Info<int> GFX_SW_DRAW_START;
|
|
||||||
extern const Info<int> GFX_SW_DRAW_END;
|
|
||||||
|
|
||||||
extern const Info<bool> GFX_PREFER_GLES;
|
extern const Info<bool> GFX_PREFER_GLES;
|
||||||
|
|
||||||
|
|
|
@ -575,7 +575,6 @@
|
||||||
<ClInclude Include="VideoBackends\OGL\VideoBackend.h" />
|
<ClInclude Include="VideoBackends\OGL\VideoBackend.h" />
|
||||||
<ClInclude Include="VideoBackends\Software\Clipper.h" />
|
<ClInclude Include="VideoBackends\Software\Clipper.h" />
|
||||||
<ClInclude Include="VideoBackends\Software\CopyRegion.h" />
|
<ClInclude Include="VideoBackends\Software\CopyRegion.h" />
|
||||||
<ClInclude Include="VideoBackends\Software\DebugUtil.h" />
|
|
||||||
<ClInclude Include="VideoBackends\Software\EfbCopy.h" />
|
<ClInclude Include="VideoBackends\Software\EfbCopy.h" />
|
||||||
<ClInclude Include="VideoBackends\Software\EfbInterface.h" />
|
<ClInclude Include="VideoBackends\Software\EfbInterface.h" />
|
||||||
<ClInclude Include="VideoBackends\Software\NativeVertexFormat.h" />
|
<ClInclude Include="VideoBackends\Software\NativeVertexFormat.h" />
|
||||||
|
@ -1183,7 +1182,6 @@
|
||||||
<ClCompile Include="VideoBackends\OGL\ProgramShaderCache.cpp" />
|
<ClCompile Include="VideoBackends\OGL\ProgramShaderCache.cpp" />
|
||||||
<ClCompile Include="VideoBackends\OGL\SamplerCache.cpp" />
|
<ClCompile Include="VideoBackends\OGL\SamplerCache.cpp" />
|
||||||
<ClCompile Include="VideoBackends\Software\Clipper.cpp" />
|
<ClCompile Include="VideoBackends\Software\Clipper.cpp" />
|
||||||
<ClCompile Include="VideoBackends\Software\DebugUtil.cpp" />
|
|
||||||
<ClCompile Include="VideoBackends\Software\EfbCopy.cpp" />
|
<ClCompile Include="VideoBackends\Software\EfbCopy.cpp" />
|
||||||
<ClCompile Include="VideoBackends\Software\EfbInterface.cpp" />
|
<ClCompile Include="VideoBackends\Software\EfbInterface.cpp" />
|
||||||
<ClCompile Include="VideoBackends\Software\Rasterizer.cpp" />
|
<ClCompile Include="VideoBackends\Software\Rasterizer.cpp" />
|
||||||
|
|
|
@ -92,8 +92,6 @@ add_executable(dolphin-emu
|
||||||
Config/Graphics/HacksWidget.h
|
Config/Graphics/HacksWidget.h
|
||||||
Config/Graphics/PostProcessingConfigWindow.cpp
|
Config/Graphics/PostProcessingConfigWindow.cpp
|
||||||
Config/Graphics/PostProcessingConfigWindow.h
|
Config/Graphics/PostProcessingConfigWindow.h
|
||||||
Config/Graphics/SoftwareRendererWidget.cpp
|
|
||||||
Config/Graphics/SoftwareRendererWidget.h
|
|
||||||
Config/GraphicsModListWidget.cpp
|
Config/GraphicsModListWidget.cpp
|
||||||
Config/GraphicsModListWidget.h
|
Config/GraphicsModListWidget.h
|
||||||
Config/GraphicsModWarningWidget.cpp
|
Config/GraphicsModWarningWidget.cpp
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
#include "DolphinQt/Config/Graphics/EnhancementsWidget.h"
|
#include "DolphinQt/Config/Graphics/EnhancementsWidget.h"
|
||||||
#include "DolphinQt/Config/Graphics/GeneralWidget.h"
|
#include "DolphinQt/Config/Graphics/GeneralWidget.h"
|
||||||
#include "DolphinQt/Config/Graphics/HacksWidget.h"
|
#include "DolphinQt/Config/Graphics/HacksWidget.h"
|
||||||
#include "DolphinQt/Config/Graphics/SoftwareRendererWidget.h"
|
|
||||||
#include "DolphinQt/MainWindow.h"
|
#include "DolphinQt/MainWindow.h"
|
||||||
#include "DolphinQt/QtUtils/WrapInScrollArea.h"
|
#include "DolphinQt/QtUtils/WrapInScrollArea.h"
|
||||||
|
|
||||||
|
@ -51,30 +50,19 @@ void GraphicsWindow::CreateMainLayout()
|
||||||
m_enhancements_widget = new EnhancementsWidget(this);
|
m_enhancements_widget = new EnhancementsWidget(this);
|
||||||
m_hacks_widget = new HacksWidget(this);
|
m_hacks_widget = new HacksWidget(this);
|
||||||
m_advanced_widget = new AdvancedWidget(this);
|
m_advanced_widget = new AdvancedWidget(this);
|
||||||
m_software_renderer = new SoftwareRendererWidget(this);
|
|
||||||
|
|
||||||
connect(m_general_widget, &GeneralWidget::BackendChanged, this,
|
connect(m_general_widget, &GeneralWidget::BackendChanged, this,
|
||||||
&GraphicsWindow::OnBackendChanged);
|
&GraphicsWindow::OnBackendChanged);
|
||||||
connect(m_software_renderer, &SoftwareRendererWidget::BackendChanged, this,
|
|
||||||
&GraphicsWindow::OnBackendChanged);
|
|
||||||
|
|
||||||
m_wrapped_general = GetWrappedWidget(m_general_widget, this, 50, 100);
|
m_wrapped_general = GetWrappedWidget(m_general_widget, this, 50, 100);
|
||||||
m_wrapped_enhancements = GetWrappedWidget(m_enhancements_widget, this, 50, 100);
|
m_wrapped_enhancements = GetWrappedWidget(m_enhancements_widget, this, 50, 100);
|
||||||
m_wrapped_hacks = GetWrappedWidget(m_hacks_widget, this, 50, 100);
|
m_wrapped_hacks = GetWrappedWidget(m_hacks_widget, this, 50, 100);
|
||||||
m_wrapped_advanced = GetWrappedWidget(m_advanced_widget, this, 50, 100);
|
m_wrapped_advanced = GetWrappedWidget(m_advanced_widget, this, 50, 100);
|
||||||
m_wrapped_software = GetWrappedWidget(m_software_renderer, this, 50, 100);
|
|
||||||
|
|
||||||
if (Config::Get(Config::MAIN_GFX_BACKEND) != "Software Renderer")
|
|
||||||
{
|
|
||||||
m_tab_widget->addTab(m_wrapped_general, tr("General"));
|
m_tab_widget->addTab(m_wrapped_general, tr("General"));
|
||||||
m_tab_widget->addTab(m_wrapped_enhancements, tr("Enhancements"));
|
m_tab_widget->addTab(m_wrapped_enhancements, tr("Enhancements"));
|
||||||
m_tab_widget->addTab(m_wrapped_hacks, tr("Hacks"));
|
m_tab_widget->addTab(m_wrapped_hacks, tr("Hacks"));
|
||||||
m_tab_widget->addTab(m_wrapped_advanced, tr("Advanced"));
|
m_tab_widget->addTab(m_wrapped_advanced, tr("Advanced"));
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_tab_widget->addTab(m_wrapped_software, tr("Software Renderer"));
|
|
||||||
}
|
|
||||||
|
|
||||||
setLayout(main_layout);
|
setLayout(main_layout);
|
||||||
}
|
}
|
||||||
|
@ -86,20 +74,6 @@ void GraphicsWindow::OnBackendChanged(const QString& backend_name)
|
||||||
|
|
||||||
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())));
|
||||||
if (backend_name == QStringLiteral("Software Renderer") && m_tab_widget->count() > 1)
|
|
||||||
{
|
|
||||||
m_tab_widget->clear();
|
|
||||||
m_tab_widget->addTab(m_wrapped_software, tr("Software Renderer"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (backend_name != QStringLiteral("Software Renderer") && m_tab_widget->count() == 1)
|
|
||||||
{
|
|
||||||
m_tab_widget->clear();
|
|
||||||
m_tab_widget->addTab(m_wrapped_general, tr("General"));
|
|
||||||
m_tab_widget->addTab(m_wrapped_enhancements, tr("Enhancements"));
|
|
||||||
m_tab_widget->addTab(m_wrapped_hacks, tr("Hacks"));
|
|
||||||
m_tab_widget->addTab(m_wrapped_advanced, tr("Advanced"));
|
|
||||||
}
|
|
||||||
|
|
||||||
emit BackendChanged(backend_name);
|
emit BackendChanged(backend_name);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,194 +0,0 @@
|
||||||
// Copyright 2017 Dolphin Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#include "DolphinQt/Config/Graphics/SoftwareRendererWidget.h"
|
|
||||||
|
|
||||||
#include <QComboBox>
|
|
||||||
#include <QGridLayout>
|
|
||||||
#include <QGroupBox>
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QSpinBox>
|
|
||||||
#include <QVBoxLayout>
|
|
||||||
|
|
||||||
#include "Core/Config/GraphicsSettings.h"
|
|
||||||
#include "Core/Config/MainSettings.h"
|
|
||||||
#include "Core/ConfigManager.h"
|
|
||||||
#include "Core/Core.h"
|
|
||||||
|
|
||||||
#include "DolphinQt/Config/Graphics/GraphicsBool.h"
|
|
||||||
#include "DolphinQt/Config/Graphics/GraphicsWindow.h"
|
|
||||||
#include "DolphinQt/Config/ToolTipControls/ToolTipComboBox.h"
|
|
||||||
#include "DolphinQt/Settings.h"
|
|
||||||
|
|
||||||
#include "UICommon/VideoUtils.h"
|
|
||||||
|
|
||||||
#include "VideoCommon/VideoBackendBase.h"
|
|
||||||
#include "VideoCommon/VideoConfig.h"
|
|
||||||
|
|
||||||
SoftwareRendererWidget::SoftwareRendererWidget(GraphicsWindow* parent)
|
|
||||||
{
|
|
||||||
CreateWidgets();
|
|
||||||
LoadSettings();
|
|
||||||
ConnectWidgets();
|
|
||||||
AddDescriptions();
|
|
||||||
emit BackendChanged(QString::fromStdString(Config::Get(Config::MAIN_GFX_BACKEND)));
|
|
||||||
|
|
||||||
connect(parent, &GraphicsWindow::BackendChanged, [this] { LoadSettings(); });
|
|
||||||
connect(&Settings::Instance(), &Settings::EmulationStateChanged, this, [this](Core::State state) {
|
|
||||||
OnEmulationStateChanged(state != Core::State::Uninitialized);
|
|
||||||
});
|
|
||||||
OnEmulationStateChanged(Core::GetState() != Core::State::Uninitialized);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SoftwareRendererWidget::CreateWidgets()
|
|
||||||
{
|
|
||||||
auto* main_layout = new QVBoxLayout;
|
|
||||||
|
|
||||||
auto* rendering_box = new QGroupBox(tr("Rendering"));
|
|
||||||
auto* rendering_layout = new QGridLayout();
|
|
||||||
m_backend_combo = new ToolTipComboBox();
|
|
||||||
|
|
||||||
rendering_box->setLayout(rendering_layout);
|
|
||||||
rendering_layout->addWidget(new QLabel(tr("Backend:")), 1, 1);
|
|
||||||
rendering_layout->addWidget(m_backend_combo, 1, 2);
|
|
||||||
|
|
||||||
for (const auto& backend : VideoBackendBase::GetAvailableBackends())
|
|
||||||
m_backend_combo->addItem(tr(backend->GetDisplayName().c_str()));
|
|
||||||
|
|
||||||
auto* overlay_box = new QGroupBox(tr("Overlay Information"));
|
|
||||||
auto* overlay_layout = new QGridLayout();
|
|
||||||
overlay_box->setLayout(overlay_layout);
|
|
||||||
m_show_statistics = new GraphicsBool(tr("Show Statistics"), Config::GFX_OVERLAY_STATS);
|
|
||||||
|
|
||||||
overlay_layout->addWidget(m_show_statistics);
|
|
||||||
|
|
||||||
auto* utility_box = new QGroupBox(tr("Utility"));
|
|
||||||
auto* utility_layout = new QGridLayout();
|
|
||||||
m_dump_textures = new GraphicsBool(tr("Dump Textures"), Config::GFX_DUMP_TEXTURES);
|
|
||||||
m_dump_objects = new GraphicsBool(tr("Dump Objects"), Config::GFX_SW_DUMP_OBJECTS);
|
|
||||||
utility_box->setLayout(utility_layout);
|
|
||||||
|
|
||||||
utility_layout->addWidget(m_dump_textures, 1, 1);
|
|
||||||
utility_layout->addWidget(m_dump_objects, 1, 2);
|
|
||||||
|
|
||||||
auto* debug_box = new QGroupBox(tr("Debug Only"));
|
|
||||||
auto* debug_layout = new QGridLayout();
|
|
||||||
m_dump_tev_stages = new GraphicsBool(tr("Dump TEV Stages"), Config::GFX_SW_DUMP_TEV_STAGES);
|
|
||||||
m_dump_tev_fetches =
|
|
||||||
new GraphicsBool(tr("Dump Texture Fetches"), Config::GFX_SW_DUMP_TEV_TEX_FETCHES);
|
|
||||||
|
|
||||||
debug_layout->addWidget(m_dump_tev_stages, 1, 1);
|
|
||||||
debug_layout->addWidget(m_dump_tev_fetches, 1, 2);
|
|
||||||
|
|
||||||
debug_box->setLayout(debug_layout);
|
|
||||||
|
|
||||||
#ifdef _DEBUG
|
|
||||||
utility_layout->addWidget(debug_box, 2, 1, 1, 2);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
auto* object_range_box = new QGroupBox(tr("Drawn Object Range"));
|
|
||||||
auto* object_range_layout = new QGridLayout();
|
|
||||||
m_object_range_min = new QSpinBox();
|
|
||||||
m_object_range_max = new QSpinBox();
|
|
||||||
|
|
||||||
for (auto* spin : {m_object_range_min, m_object_range_max})
|
|
||||||
{
|
|
||||||
spin->setMinimum(0);
|
|
||||||
spin->setMaximum(100000);
|
|
||||||
}
|
|
||||||
|
|
||||||
object_range_box->setLayout(object_range_layout);
|
|
||||||
|
|
||||||
object_range_layout->addWidget(m_object_range_min, 1, 1);
|
|
||||||
object_range_layout->addWidget(m_object_range_max, 1, 2);
|
|
||||||
|
|
||||||
main_layout->addWidget(rendering_box);
|
|
||||||
main_layout->addWidget(overlay_box);
|
|
||||||
main_layout->addWidget(utility_box);
|
|
||||||
main_layout->addWidget(object_range_box);
|
|
||||||
main_layout->addStretch();
|
|
||||||
|
|
||||||
setLayout(main_layout);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SoftwareRendererWidget::ConnectWidgets()
|
|
||||||
{
|
|
||||||
connect(m_backend_combo, qOverload<int>(&QComboBox::currentIndexChanged),
|
|
||||||
[this](int) { SaveSettings(); });
|
|
||||||
connect(m_object_range_min, qOverload<int>(&QSpinBox::valueChanged),
|
|
||||||
[this](int) { SaveSettings(); });
|
|
||||||
connect(m_object_range_max, qOverload<int>(&QSpinBox::valueChanged),
|
|
||||||
[this](int) { SaveSettings(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
void SoftwareRendererWidget::LoadSettings()
|
|
||||||
{
|
|
||||||
for (const auto& backend : VideoBackendBase::GetAvailableBackends())
|
|
||||||
{
|
|
||||||
if (backend->GetName() == Config::Get(Config::MAIN_GFX_BACKEND))
|
|
||||||
{
|
|
||||||
m_backend_combo->setCurrentIndex(
|
|
||||||
m_backend_combo->findText(tr(backend->GetDisplayName().c_str())));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_object_range_min->setValue(Config::Get(Config::GFX_SW_DRAW_START));
|
|
||||||
m_object_range_max->setValue(Config::Get(Config::GFX_SW_DRAW_END));
|
|
||||||
}
|
|
||||||
|
|
||||||
void SoftwareRendererWidget::SaveSettings()
|
|
||||||
{
|
|
||||||
for (const auto& backend : VideoBackendBase::GetAvailableBackends())
|
|
||||||
{
|
|
||||||
if (tr(backend->GetDisplayName().c_str()) == m_backend_combo->currentText())
|
|
||||||
{
|
|
||||||
const auto backend_name = backend->GetName();
|
|
||||||
if (backend_name != Config::Get(Config::MAIN_GFX_BACKEND))
|
|
||||||
emit BackendChanged(QString::fromStdString(backend_name));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Config::SetBaseOrCurrent(Config::GFX_SW_DRAW_START, m_object_range_min->value());
|
|
||||||
Config::SetBaseOrCurrent(Config::GFX_SW_DRAW_END, m_object_range_max->value());
|
|
||||||
}
|
|
||||||
|
|
||||||
void SoftwareRendererWidget::AddDescriptions()
|
|
||||||
{
|
|
||||||
static const char TR_BACKEND_DESCRIPTION[] = QT_TR_NOOP(
|
|
||||||
"Selects what graphics API to use internally.<br>The software renderer is extremely "
|
|
||||||
"slow and only useful for debugging, so you'll want to use either Direct3D or "
|
|
||||||
"OpenGL. Different games and different GPUs will behave differently on each "
|
|
||||||
"backend, so for the best emulation experience it's recommended to try both and "
|
|
||||||
"choose the one that's less problematic.<br><br><dolphin_emphasis>If unsure, select "
|
|
||||||
"OpenGL.</dolphin_emphasis>");
|
|
||||||
static const char TR_SHOW_STATISTICS_DESCRIPTION[] =
|
|
||||||
QT_TR_NOOP("Show various rendering statistics.<br><br><dolphin_emphasis>If unsure, leave "
|
|
||||||
"this unchecked.</dolphin_emphasis>");
|
|
||||||
static const char TR_DUMP_TEXTURES_DESCRIPTION[] =
|
|
||||||
QT_TR_NOOP("Dump decoded game textures to "
|
|
||||||
"User/Dump/Textures/<game_id>/.<br><br><dolphin_emphasis>If unsure, leave "
|
|
||||||
"this unchecked.</dolphin_emphasis>");
|
|
||||||
static const char TR_DUMP_OBJECTS_DESCRIPTION[] =
|
|
||||||
QT_TR_NOOP("Dump objects to User/Dump/Objects/.<br><br><dolphin_emphasis>If unsure, leave "
|
|
||||||
"this unchecked.</dolphin_emphasis>");
|
|
||||||
static const char TR_DUMP_TEV_STAGES_DESCRIPTION[] =
|
|
||||||
QT_TR_NOOP("Dump TEV Stages to User/Dump/Objects/.<br><br><dolphin_emphasis>If unsure, leave "
|
|
||||||
"this unchecked.</dolphin_emphasis>");
|
|
||||||
static const char TR_DUMP_TEV_FETCHES_DESCRIPTION[] = QT_TR_NOOP(
|
|
||||||
"Dump Texture Fetches to User/Dump/Objects/.<br><br><dolphin_emphasis>If unsure, leave "
|
|
||||||
"this unchecked.</dolphin_emphasis>");
|
|
||||||
|
|
||||||
m_backend_combo->SetTitle(tr("Backend"));
|
|
||||||
m_backend_combo->SetDescription(tr(TR_BACKEND_DESCRIPTION));
|
|
||||||
m_show_statistics->SetDescription(tr(TR_SHOW_STATISTICS_DESCRIPTION));
|
|
||||||
m_dump_textures->SetDescription(tr(TR_DUMP_TEXTURES_DESCRIPTION));
|
|
||||||
m_dump_objects->SetDescription(tr(TR_DUMP_OBJECTS_DESCRIPTION));
|
|
||||||
m_dump_tev_stages->SetDescription(tr(TR_DUMP_TEV_STAGES_DESCRIPTION));
|
|
||||||
m_dump_tev_fetches->SetDescription(tr(TR_DUMP_TEV_FETCHES_DESCRIPTION));
|
|
||||||
}
|
|
||||||
|
|
||||||
void SoftwareRendererWidget::OnEmulationStateChanged(bool running)
|
|
||||||
{
|
|
||||||
m_backend_combo->setEnabled(!running);
|
|
||||||
}
|
|
|
@ -1,41 +0,0 @@
|
||||||
// Copyright 2017 Dolphin Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "DolphinQt/Config/Graphics/GraphicsWidget.h"
|
|
||||||
|
|
||||||
class GraphicsBool;
|
|
||||||
class GraphicsWindow;
|
|
||||||
class QSpinBox;
|
|
||||||
class ToolTipComboBox;
|
|
||||||
|
|
||||||
class SoftwareRendererWidget final : public GraphicsWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit SoftwareRendererWidget(GraphicsWindow* parent);
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void BackendChanged(const QString& backend);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void LoadSettings() override;
|
|
||||||
void SaveSettings() override;
|
|
||||||
|
|
||||||
void CreateWidgets();
|
|
||||||
void ConnectWidgets();
|
|
||||||
void AddDescriptions();
|
|
||||||
|
|
||||||
void OnEmulationStateChanged(bool running);
|
|
||||||
|
|
||||||
ToolTipComboBox* m_backend_combo;
|
|
||||||
GraphicsBool* m_show_statistics;
|
|
||||||
GraphicsBool* m_dump_textures;
|
|
||||||
GraphicsBool* m_dump_objects;
|
|
||||||
GraphicsBool* m_dump_tev_stages;
|
|
||||||
GraphicsBool* m_dump_tev_fetches;
|
|
||||||
|
|
||||||
QSpinBox* m_object_range_min;
|
|
||||||
QSpinBox* m_object_range_max;
|
|
||||||
};
|
|
|
@ -79,7 +79,6 @@
|
||||||
<ClCompile Include="Config\Graphics\GraphicsWindow.cpp" />
|
<ClCompile Include="Config\Graphics\GraphicsWindow.cpp" />
|
||||||
<ClCompile Include="Config\Graphics\HacksWidget.cpp" />
|
<ClCompile Include="Config\Graphics\HacksWidget.cpp" />
|
||||||
<ClCompile Include="Config\Graphics\PostProcessingConfigWindow.cpp" />
|
<ClCompile Include="Config\Graphics\PostProcessingConfigWindow.cpp" />
|
||||||
<ClCompile Include="Config\Graphics\SoftwareRendererWidget.cpp" />
|
|
||||||
<ClCompile Include="Config\GraphicsModListWidget.cpp" />
|
<ClCompile Include="Config\GraphicsModListWidget.cpp" />
|
||||||
<ClCompile Include="Config\GraphicsModWarningWidget.cpp" />
|
<ClCompile Include="Config\GraphicsModWarningWidget.cpp" />
|
||||||
<ClCompile Include="Config\InfoWidget.cpp" />
|
<ClCompile Include="Config\InfoWidget.cpp" />
|
||||||
|
@ -276,7 +275,6 @@
|
||||||
<QtMoc Include="Config\Graphics\GraphicsWindow.h" />
|
<QtMoc Include="Config\Graphics\GraphicsWindow.h" />
|
||||||
<QtMoc Include="Config\Graphics\HacksWidget.h" />
|
<QtMoc Include="Config\Graphics\HacksWidget.h" />
|
||||||
<QtMoc Include="Config\Graphics\PostProcessingConfigWindow.h" />
|
<QtMoc Include="Config\Graphics\PostProcessingConfigWindow.h" />
|
||||||
<QtMoc Include="Config\Graphics\SoftwareRendererWidget.h" />
|
|
||||||
<QtMoc Include="Config\GraphicsModListWidget.h" />
|
<QtMoc Include="Config\GraphicsModListWidget.h" />
|
||||||
<QtMoc Include="Config\GraphicsModWarningWidget.h" />
|
<QtMoc Include="Config\GraphicsModWarningWidget.h" />
|
||||||
<QtMoc Include="Config\InfoWidget.h" />
|
<QtMoc Include="Config\InfoWidget.h" />
|
||||||
|
|
|
@ -2,8 +2,6 @@ add_library(videosoftware
|
||||||
Clipper.cpp
|
Clipper.cpp
|
||||||
Clipper.h
|
Clipper.h
|
||||||
CopyRegion.h
|
CopyRegion.h
|
||||||
DebugUtil.cpp
|
|
||||||
DebugUtil.h
|
|
||||||
EfbCopy.cpp
|
EfbCopy.cpp
|
||||||
EfbCopy.h
|
EfbCopy.h
|
||||||
EfbInterface.cpp
|
EfbInterface.cpp
|
||||||
|
|
|
@ -1,219 +0,0 @@
|
||||||
// Copyright 2009 Dolphin Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#include "VideoBackends/Software/DebugUtil.h"
|
|
||||||
|
|
||||||
#include <cstring>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include "Common/CommonTypes.h"
|
|
||||||
#include "Common/FileUtil.h"
|
|
||||||
#include "Common/Image.h"
|
|
||||||
#include "Common/StringUtil.h"
|
|
||||||
#include "Common/Swap.h"
|
|
||||||
|
|
||||||
#include "VideoBackends/Software/EfbInterface.h"
|
|
||||||
#include "VideoBackends/Software/TextureSampler.h"
|
|
||||||
|
|
||||||
#include "VideoCommon/BPMemory.h"
|
|
||||||
#include "VideoCommon/Statistics.h"
|
|
||||||
#include "VideoCommon/VideoCommon.h"
|
|
||||||
#include "VideoCommon/VideoConfig.h"
|
|
||||||
|
|
||||||
namespace DebugUtil
|
|
||||||
{
|
|
||||||
static const int NUM_OBJECT_BUFFERS = 40;
|
|
||||||
|
|
||||||
static u32* ObjectBuffer[NUM_OBJECT_BUFFERS];
|
|
||||||
static u32 TempBuffer[NUM_OBJECT_BUFFERS];
|
|
||||||
|
|
||||||
static bool DrawnToBuffer[NUM_OBJECT_BUFFERS];
|
|
||||||
static const char* ObjectBufferName[NUM_OBJECT_BUFFERS];
|
|
||||||
static int BufferBase[NUM_OBJECT_BUFFERS];
|
|
||||||
|
|
||||||
void Init()
|
|
||||||
{
|
|
||||||
for (int i = 0; i < NUM_OBJECT_BUFFERS; i++)
|
|
||||||
{
|
|
||||||
ObjectBuffer[i] = new u32[EFB_WIDTH * EFB_HEIGHT]();
|
|
||||||
DrawnToBuffer[i] = false;
|
|
||||||
ObjectBufferName[i] = nullptr;
|
|
||||||
BufferBase[i] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Shutdown()
|
|
||||||
{
|
|
||||||
for (auto& slot : ObjectBuffer)
|
|
||||||
{
|
|
||||||
delete[] slot;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void SaveTexture(const std::string& filename, u32 texmap, s32 mip)
|
|
||||||
{
|
|
||||||
u32 width = bpmem.tex.GetUnit(texmap).texImage0.width + 1;
|
|
||||||
u32 height = bpmem.tex.GetUnit(texmap).texImage0.height + 1;
|
|
||||||
|
|
||||||
auto data = std::make_unique<u8[]>(width * height * 4);
|
|
||||||
|
|
||||||
GetTextureRGBA(data.get(), texmap, mip, width, height);
|
|
||||||
Common::SavePNG(filename, data.get(), Common::ImageByteFormat::RGBA, width, height, width * 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetTextureRGBA(u8* dst, u32 texmap, s32 mip, u32 width, u32 height)
|
|
||||||
{
|
|
||||||
for (u32 y = 0; y < height; y++)
|
|
||||||
{
|
|
||||||
for (u32 x = 0; x < width; x++)
|
|
||||||
{
|
|
||||||
TextureSampler::SampleMip(x << 7, y << 7, mip, false, texmap, dst);
|
|
||||||
dst += 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static s32 GetMaxTextureLod(u32 texmap)
|
|
||||||
{
|
|
||||||
u8 maxLod = bpmem.tex.GetUnit(texmap).texMode1.max_lod;
|
|
||||||
u8 mip = maxLod >> 4;
|
|
||||||
u8 fract = maxLod & 0xf;
|
|
||||||
|
|
||||||
if (fract)
|
|
||||||
++mip;
|
|
||||||
|
|
||||||
return (s32)mip;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DumpActiveTextures()
|
|
||||||
{
|
|
||||||
for (unsigned int stageNum = 0; stageNum < bpmem.genMode.numindstages; stageNum++)
|
|
||||||
{
|
|
||||||
u32 texmap = bpmem.tevindref.getTexMap(stageNum);
|
|
||||||
|
|
||||||
s32 maxLod = GetMaxTextureLod(texmap);
|
|
||||||
for (s32 mip = 0; mip <= maxLod; ++mip)
|
|
||||||
{
|
|
||||||
SaveTexture(StringFromFormat("%star%i_ind%i_map%i_mip%i.png",
|
|
||||||
File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(),
|
|
||||||
g_stats.this_frame.num_drawn_objects, stageNum, texmap, mip),
|
|
||||||
texmap, mip);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (unsigned int stageNum = 0; stageNum <= bpmem.genMode.numtevstages; stageNum++)
|
|
||||||
{
|
|
||||||
int stageNum2 = stageNum >> 1;
|
|
||||||
int stageOdd = stageNum & 1;
|
|
||||||
TwoTevStageOrders& order = bpmem.tevorders[stageNum2];
|
|
||||||
|
|
||||||
int texmap = order.getTexMap(stageOdd);
|
|
||||||
|
|
||||||
s32 maxLod = GetMaxTextureLod(texmap);
|
|
||||||
for (s32 mip = 0; mip <= maxLod; ++mip)
|
|
||||||
{
|
|
||||||
SaveTexture(StringFromFormat("%star%i_stage%i_map%i_mip%i.png",
|
|
||||||
File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(),
|
|
||||||
g_stats.this_frame.num_drawn_objects, stageNum, texmap, mip),
|
|
||||||
texmap, mip);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void DumpEfb(const std::string& filename)
|
|
||||||
{
|
|
||||||
auto data = std::make_unique<u8[]>(EFB_WIDTH * EFB_HEIGHT * 4);
|
|
||||||
u8* writePtr = data.get();
|
|
||||||
|
|
||||||
for (u32 y = 0; y < EFB_HEIGHT; y++)
|
|
||||||
{
|
|
||||||
for (u32 x = 0; x < EFB_WIDTH; x++)
|
|
||||||
{
|
|
||||||
// ABGR to RGBA
|
|
||||||
const u32 sample = Common::swap32(EfbInterface::GetColor(x, y));
|
|
||||||
|
|
||||||
std::memcpy(writePtr, &sample, sizeof(u32));
|
|
||||||
writePtr += sizeof(u32);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Common::SavePNG(filename, data.get(), Common::ImageByteFormat::RGBA, EFB_WIDTH, EFB_HEIGHT,
|
|
||||||
EFB_WIDTH * 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DrawObjectBuffer(s16 x, s16 y, const u8* color, int bufferBase, int subBuffer,
|
|
||||||
const char* name)
|
|
||||||
{
|
|
||||||
int buffer = bufferBase + subBuffer;
|
|
||||||
|
|
||||||
u32 offset = (x + y * EFB_WIDTH) * 4;
|
|
||||||
u8* dst = (u8*)&ObjectBuffer[buffer][offset];
|
|
||||||
*(dst++) = color[2];
|
|
||||||
*(dst++) = color[1];
|
|
||||||
*(dst++) = color[0];
|
|
||||||
*(dst++) = color[3];
|
|
||||||
|
|
||||||
DrawnToBuffer[buffer] = true;
|
|
||||||
ObjectBufferName[buffer] = name;
|
|
||||||
BufferBase[buffer] = bufferBase;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DrawTempBuffer(const u8* color, int buffer)
|
|
||||||
{
|
|
||||||
u8* dst = (u8*)&TempBuffer[buffer];
|
|
||||||
*(dst++) = color[2];
|
|
||||||
*(dst++) = color[1];
|
|
||||||
*(dst++) = color[0];
|
|
||||||
*(dst++) = color[3];
|
|
||||||
}
|
|
||||||
|
|
||||||
void CopyTempBuffer(s16 x, s16 y, int bufferBase, int subBuffer, const char* name)
|
|
||||||
{
|
|
||||||
int buffer = bufferBase + subBuffer;
|
|
||||||
|
|
||||||
u32 offset = (x + y * EFB_WIDTH);
|
|
||||||
ObjectBuffer[buffer][offset] = TempBuffer[buffer];
|
|
||||||
|
|
||||||
DrawnToBuffer[buffer] = true;
|
|
||||||
ObjectBufferName[buffer] = name;
|
|
||||||
BufferBase[buffer] = bufferBase;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnObjectBegin()
|
|
||||||
{
|
|
||||||
if (g_ActiveConfig.bDumpTextures &&
|
|
||||||
g_stats.this_frame.num_drawn_objects >= g_ActiveConfig.drawStart &&
|
|
||||||
g_stats.this_frame.num_drawn_objects < g_ActiveConfig.drawEnd)
|
|
||||||
{
|
|
||||||
DumpActiveTextures();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnObjectEnd()
|
|
||||||
{
|
|
||||||
if (g_ActiveConfig.bDumpObjects &&
|
|
||||||
g_stats.this_frame.num_drawn_objects >= g_ActiveConfig.drawStart &&
|
|
||||||
g_stats.this_frame.num_drawn_objects < g_ActiveConfig.drawEnd)
|
|
||||||
{
|
|
||||||
DumpEfb(StringFromFormat("%sobject%i.png", File::GetUserPath(D_DUMPOBJECTS_IDX).c_str(),
|
|
||||||
g_stats.this_frame.num_drawn_objects));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < NUM_OBJECT_BUFFERS; i++)
|
|
||||||
{
|
|
||||||
if (DrawnToBuffer[i])
|
|
||||||
{
|
|
||||||
DrawnToBuffer[i] = false;
|
|
||||||
std::string filename = StringFromFormat(
|
|
||||||
"%sobject%i_%s(%i).png", File::GetUserPath(D_DUMPOBJECTS_IDX).c_str(),
|
|
||||||
g_stats.this_frame.num_drawn_objects, ObjectBufferName[i], i - BufferBase[i]);
|
|
||||||
|
|
||||||
Common::SavePNG(filename, reinterpret_cast<u8*>(ObjectBuffer[i]),
|
|
||||||
Common::ImageByteFormat::RGBA, EFB_WIDTH, EFB_HEIGHT, EFB_WIDTH * 4);
|
|
||||||
memset(ObjectBuffer[i], 0, EFB_WIDTH * EFB_HEIGHT * sizeof(u32));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
g_stats.this_frame.num_drawn_objects++;
|
|
||||||
}
|
|
||||||
} // namespace DebugUtil
|
|
|
@ -1,25 +0,0 @@
|
||||||
// Copyright 2008 Dolphin Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Common/CommonTypes.h"
|
|
||||||
|
|
||||||
namespace DebugUtil
|
|
||||||
{
|
|
||||||
void Init();
|
|
||||||
void Shutdown();
|
|
||||||
|
|
||||||
void GetTextureRGBA(u8* dst, u32 texmap, s32 mip, u32 width, u32 height);
|
|
||||||
|
|
||||||
void DumpActiveTextures();
|
|
||||||
|
|
||||||
void OnObjectBegin();
|
|
||||||
void OnObjectEnd();
|
|
||||||
|
|
||||||
void DrawObjectBuffer(s16 x, s16 y, const u8* color, int bufferBase, int subBuffer,
|
|
||||||
const char* name);
|
|
||||||
|
|
||||||
void DrawTempBuffer(const u8* color, int buffer);
|
|
||||||
void CopyTempBuffer(s16 x, s16 y, int bufferBase, int subBuffer, const char* name);
|
|
||||||
} // namespace DebugUtil
|
|
|
@ -105,7 +105,7 @@ void SWOGLWindow::ShowImage(const AbstractTexture* image,
|
||||||
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, static_cast<GLsizei>(sw_image->GetConfig().width),
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, static_cast<GLsizei>(sw_image->GetConfig().width),
|
||||||
static_cast<GLsizei>(sw_image->GetConfig().height), 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
static_cast<GLsizei>(sw_image->GetConfig().height), 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||||
sw_image->GetData());
|
sw_image->GetData(0, 0));
|
||||||
|
|
||||||
glUseProgram(m_image_program);
|
glUseProgram(m_image_program);
|
||||||
|
|
||||||
|
|
|
@ -25,17 +25,17 @@ struct Pixel
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
void CopyTextureData(const TextureConfig& src_config, const u8* src_ptr, u32 src_x, u32 src_y,
|
void CopyTextureData(const TextureConfig& src_config, const u8* src_ptr, u32 src_x, u32 src_y,
|
||||||
u32 width, u32 height, const TextureConfig& dst_config, u8* dst_ptr, u32 dst_x,
|
u32 width, u32 height, u32 src_level, const TextureConfig& dst_config,
|
||||||
u32 dst_y)
|
u8* dst_ptr, u32 dst_x, u32 dst_y, u32 dst_level)
|
||||||
{
|
{
|
||||||
size_t texel_size = AbstractTexture::GetTexelSizeForFormat(src_config.format);
|
const size_t texel_size = AbstractTexture::GetTexelSizeForFormat(src_config.format);
|
||||||
size_t src_stride = src_config.GetStride();
|
const size_t src_stride = src_config.GetMipStride(src_level);
|
||||||
size_t src_offset =
|
const size_t src_offset =
|
||||||
static_cast<size_t>(src_y) * src_stride + static_cast<size_t>(src_x) * texel_size;
|
static_cast<size_t>(src_y) * src_stride + static_cast<size_t>(src_x) * texel_size;
|
||||||
size_t dst_stride = dst_config.GetStride();
|
const size_t dst_stride = dst_config.GetMipStride(dst_level);
|
||||||
size_t dst_offset =
|
const size_t dst_offset =
|
||||||
static_cast<size_t>(dst_y) * dst_stride + static_cast<size_t>(dst_x) * texel_size;
|
static_cast<size_t>(dst_y) * dst_stride + static_cast<size_t>(dst_x) * texel_size;
|
||||||
size_t copy_len = static_cast<size_t>(width) * texel_size;
|
const size_t copy_len = static_cast<size_t>(width) * texel_size;
|
||||||
|
|
||||||
src_ptr += src_offset;
|
src_ptr += src_offset;
|
||||||
dst_ptr += dst_offset;
|
dst_ptr += dst_offset;
|
||||||
|
@ -56,15 +56,24 @@ void SWRenderer::ScaleTexture(AbstractFramebuffer* dst_framebuffer,
|
||||||
const SWTexture* software_source_texture = static_cast<const SWTexture*>(src_texture);
|
const SWTexture* software_source_texture = static_cast<const SWTexture*>(src_texture);
|
||||||
SWTexture* software_dest_texture = static_cast<SWTexture*>(dst_framebuffer->GetColorAttachment());
|
SWTexture* software_dest_texture = static_cast<SWTexture*>(dst_framebuffer->GetColorAttachment());
|
||||||
|
|
||||||
CopyRegion(reinterpret_cast<const Pixel*>(software_source_texture->GetData()), src_rect,
|
CopyRegion(reinterpret_cast<const Pixel*>(software_source_texture->GetData(0, 0)), src_rect,
|
||||||
src_texture->GetWidth(), src_texture->GetHeight(),
|
src_texture->GetWidth(), src_texture->GetHeight(),
|
||||||
reinterpret_cast<Pixel*>(software_dest_texture->GetData()), dst_rect,
|
reinterpret_cast<Pixel*>(software_dest_texture->GetData(0, 0)), dst_rect,
|
||||||
dst_framebuffer->GetWidth(), dst_framebuffer->GetHeight());
|
dst_framebuffer->GetWidth(), dst_framebuffer->GetHeight());
|
||||||
}
|
}
|
||||||
|
|
||||||
SWTexture::SWTexture(const TextureConfig& tex_config) : AbstractTexture(tex_config)
|
SWTexture::SWTexture(const TextureConfig& tex_config) : AbstractTexture(tex_config)
|
||||||
{
|
{
|
||||||
m_data.resize(tex_config.width * tex_config.height * 4);
|
m_data.resize(tex_config.layers);
|
||||||
|
for (u32 layer = 0; layer < tex_config.layers; layer++)
|
||||||
|
{
|
||||||
|
m_data[layer].resize(tex_config.levels);
|
||||||
|
for (u32 level = 0; level < tex_config.levels; level++)
|
||||||
|
{
|
||||||
|
m_data[layer][level].resize(std::max(tex_config.width >> level, 1u) *
|
||||||
|
std::max(tex_config.height >> level, 1u) * sizeof(Pixel));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SWTexture::CopyRectangleFromTexture(const AbstractTexture* src,
|
void SWTexture::CopyRectangleFromTexture(const AbstractTexture* src,
|
||||||
|
@ -72,10 +81,10 @@ void SWTexture::CopyRectangleFromTexture(const AbstractTexture* src,
|
||||||
u32 src_level, const MathUtil::Rectangle<int>& dst_rect,
|
u32 src_level, const MathUtil::Rectangle<int>& dst_rect,
|
||||||
u32 dst_layer, u32 dst_level)
|
u32 dst_layer, u32 dst_level)
|
||||||
{
|
{
|
||||||
ASSERT(src_level == 0 && src_layer == 0 && dst_layer == 0 && dst_level == 0);
|
CopyTextureData(src->GetConfig(),
|
||||||
CopyTextureData(src->GetConfig(), static_cast<const SWTexture*>(src)->m_data.data(),
|
static_cast<const SWTexture*>(src)->GetData(src_layer, src_level), src_rect.left,
|
||||||
src_rect.left, src_rect.top, src_rect.GetWidth(), src_rect.GetHeight(), m_config,
|
src_rect.top, src_rect.GetWidth(), src_rect.GetHeight(), src_level, m_config,
|
||||||
m_data.data(), dst_rect.left, dst_rect.top);
|
GetData(dst_layer, dst_level), dst_rect.left, dst_rect.top, dst_level);
|
||||||
}
|
}
|
||||||
void SWTexture::ResolveFromTexture(const AbstractTexture* src, const MathUtil::Rectangle<int>& rect,
|
void SWTexture::ResolveFromTexture(const AbstractTexture* src, const MathUtil::Rectangle<int>& rect,
|
||||||
u32 layer, u32 level)
|
u32 layer, u32 level)
|
||||||
|
@ -85,17 +94,25 @@ void SWTexture::ResolveFromTexture(const AbstractTexture* src, const MathUtil::R
|
||||||
void SWTexture::Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer,
|
void SWTexture::Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer,
|
||||||
size_t buffer_size)
|
size_t buffer_size)
|
||||||
{
|
{
|
||||||
m_data.assign(buffer, buffer + buffer_size);
|
for (u32 layer = 0; layer < m_config.layers; layer++)
|
||||||
|
{
|
||||||
|
u8* data = GetData(layer, level);
|
||||||
|
for (u32 y = 0; y < height; y++)
|
||||||
|
{
|
||||||
|
memcpy(&data[width * y * sizeof(Pixel)], &buffer[y * row_length * sizeof(Pixel)],
|
||||||
|
width * sizeof(Pixel));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const u8* SWTexture::GetData() const
|
const u8* SWTexture::GetData(u32 layer, u32 level) const
|
||||||
{
|
{
|
||||||
return m_data.data();
|
return m_data[layer][level].data();
|
||||||
}
|
}
|
||||||
|
|
||||||
u8* SWTexture::GetData()
|
u8* SWTexture::GetData(u32 layer, u32 level)
|
||||||
{
|
{
|
||||||
return m_data.data();
|
return m_data[layer][level].data();
|
||||||
}
|
}
|
||||||
|
|
||||||
SWStagingTexture::SWStagingTexture(StagingTextureType type, const TextureConfig& config)
|
SWStagingTexture::SWStagingTexture(StagingTextureType type, const TextureConfig& config)
|
||||||
|
@ -112,10 +129,10 @@ void SWStagingTexture::CopyFromTexture(const AbstractTexture* src,
|
||||||
const MathUtil::Rectangle<int>& src_rect, u32 src_layer,
|
const MathUtil::Rectangle<int>& src_rect, u32 src_layer,
|
||||||
u32 src_level, const MathUtil::Rectangle<int>& dst_rect)
|
u32 src_level, const MathUtil::Rectangle<int>& dst_rect)
|
||||||
{
|
{
|
||||||
ASSERT(src_level == 0 && src_layer == 0);
|
CopyTextureData(src->GetConfig(),
|
||||||
CopyTextureData(src->GetConfig(), static_cast<const SWTexture*>(src)->GetData(), src_rect.left,
|
static_cast<const SWTexture*>(src)->GetData(src_layer, src_level), src_rect.left,
|
||||||
src_rect.top, src_rect.GetWidth(), src_rect.GetHeight(), m_config, m_data.data(),
|
src_rect.top, src_rect.GetWidth(), src_rect.GetHeight(), src_level, m_config,
|
||||||
dst_rect.left, dst_rect.top);
|
m_data.data(), dst_rect.left, dst_rect.top, 0);
|
||||||
m_needs_flush = true;
|
m_needs_flush = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,10 +140,10 @@ void SWStagingTexture::CopyToTexture(const MathUtil::Rectangle<int>& src_rect, A
|
||||||
const MathUtil::Rectangle<int>& dst_rect, u32 dst_layer,
|
const MathUtil::Rectangle<int>& dst_rect, u32 dst_layer,
|
||||||
u32 dst_level)
|
u32 dst_level)
|
||||||
{
|
{
|
||||||
ASSERT(dst_level == 0 && dst_layer == 0);
|
|
||||||
CopyTextureData(m_config, m_data.data(), src_rect.left, src_rect.top, src_rect.GetWidth(),
|
CopyTextureData(m_config, m_data.data(), src_rect.left, src_rect.top, src_rect.GetWidth(),
|
||||||
src_rect.GetHeight(), dst->GetConfig(), static_cast<SWTexture*>(dst)->GetData(),
|
src_rect.GetHeight(), 0, dst->GetConfig(),
|
||||||
dst_rect.left, dst_rect.top);
|
static_cast<SWTexture*>(dst)->GetData(dst_layer, dst_level), dst_rect.left,
|
||||||
|
dst_rect.top, dst_level);
|
||||||
m_needs_flush = true;
|
m_needs_flush = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,11 +29,11 @@ public:
|
||||||
void Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer,
|
void Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer,
|
||||||
size_t buffer_size) override;
|
size_t buffer_size) override;
|
||||||
|
|
||||||
const u8* GetData() const;
|
const u8* GetData(u32 layer, u32 level) const;
|
||||||
u8* GetData();
|
u8* GetData(u32 layer, u32 level);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<u8> m_data;
|
std::vector<std::vector<std::vector<u8>>> m_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SWStagingTexture final : public AbstractStagingTexture
|
class SWStagingTexture final : public AbstractStagingTexture
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
|
|
||||||
#include "VideoBackends/Software/DebugUtil.h"
|
|
||||||
#include "VideoBackends/Software/NativeVertexFormat.h"
|
#include "VideoBackends/Software/NativeVertexFormat.h"
|
||||||
#include "VideoBackends/Software/Rasterizer.h"
|
#include "VideoBackends/Software/Rasterizer.h"
|
||||||
#include "VideoBackends/Software/SWRenderer.h"
|
#include "VideoBackends/Software/SWRenderer.h"
|
||||||
|
@ -42,8 +41,6 @@ DataReader SWVertexLoader::PrepareForAdditionalData(OpcodeDecoder::Primitive pri
|
||||||
|
|
||||||
void SWVertexLoader::DrawCurrentBatch(u32 base_index, u32 num_indices, u32 base_vertex)
|
void SWVertexLoader::DrawCurrentBatch(u32 base_index, u32 num_indices, u32 base_vertex)
|
||||||
{
|
{
|
||||||
DebugUtil::OnObjectBegin();
|
|
||||||
|
|
||||||
using OpcodeDecoder::Primitive;
|
using OpcodeDecoder::Primitive;
|
||||||
Primitive primitive_type = Primitive::GX_DRAW_QUADS;
|
Primitive primitive_type = Primitive::GX_DRAW_QUADS;
|
||||||
switch (m_current_primitive_type)
|
switch (m_current_primitive_type)
|
||||||
|
@ -90,10 +87,10 @@ void SWVertexLoader::DrawCurrentBatch(u32 base_index, u32 num_indices, u32 base_
|
||||||
// assemble and rasterize the primitive
|
// assemble and rasterize the primitive
|
||||||
m_setup_unit.SetupVertex();
|
m_setup_unit.SetupVertex();
|
||||||
|
|
||||||
INCSTAT(g_stats.this_frame.num_vertices_loaded)
|
INCSTAT(g_stats.this_frame.num_vertices_loaded);
|
||||||
}
|
}
|
||||||
|
|
||||||
DebugUtil::OnObjectEnd();
|
INCSTAT(g_stats.this_frame.num_drawn_objects);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SWVertexLoader::SetFormat()
|
void SWVertexLoader::SetFormat()
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
#include "Common/MsgHandler.h"
|
#include "Common/MsgHandler.h"
|
||||||
|
|
||||||
#include "VideoBackends/Software/Clipper.h"
|
#include "VideoBackends/Software/Clipper.h"
|
||||||
#include "VideoBackends/Software/DebugUtil.h"
|
|
||||||
#include "VideoBackends/Software/EfbInterface.h"
|
#include "VideoBackends/Software/EfbInterface.h"
|
||||||
#include "VideoBackends/Software/Rasterizer.h"
|
#include "VideoBackends/Software/Rasterizer.h"
|
||||||
#include "VideoBackends/Software/SWOGLWindow.h"
|
#include "VideoBackends/Software/SWOGLWindow.h"
|
||||||
|
@ -105,7 +104,6 @@ bool VideoSoftware::Initialize(const WindowSystemInfo& wsi)
|
||||||
|
|
||||||
Clipper::Init();
|
Clipper::Init();
|
||||||
Rasterizer::Init();
|
Rasterizer::Init();
|
||||||
DebugUtil::Init();
|
|
||||||
|
|
||||||
g_renderer = std::make_unique<SWRenderer>(std::move(window));
|
g_renderer = std::make_unique<SWRenderer>(std::move(window));
|
||||||
g_vertex_manager = std::make_unique<SWVertexLoader>();
|
g_vertex_manager = std::make_unique<SWVertexLoader>();
|
||||||
|
@ -135,7 +133,6 @@ void VideoSoftware::Shutdown()
|
||||||
if (g_renderer)
|
if (g_renderer)
|
||||||
g_renderer->Shutdown();
|
g_renderer->Shutdown();
|
||||||
|
|
||||||
DebugUtil::Shutdown();
|
|
||||||
g_texture_cache.reset();
|
g_texture_cache.reset();
|
||||||
g_perf_query.reset();
|
g_perf_query.reset();
|
||||||
g_framebuffer_manager.reset();
|
g_framebuffer_manager.reset();
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
|
|
||||||
#include "Common/ChunkFile.h"
|
#include "Common/ChunkFile.h"
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "VideoBackends/Software/DebugUtil.h"
|
|
||||||
#include "VideoBackends/Software/EfbInterface.h"
|
#include "VideoBackends/Software/EfbInterface.h"
|
||||||
#include "VideoBackends/Software/SWBoundingBox.h"
|
#include "VideoBackends/Software/SWBoundingBox.h"
|
||||||
#include "VideoBackends/Software/TextureSampler.h"
|
#include "VideoBackends/Software/TextureSampler.h"
|
||||||
|
@ -428,16 +427,6 @@ void Tev::Draw()
|
||||||
TextureSampler::Sample(Uv[texcoordSel].s >> scaleS, Uv[texcoordSel].t >> scaleT,
|
TextureSampler::Sample(Uv[texcoordSel].s >> scaleS, Uv[texcoordSel].t >> scaleT,
|
||||||
IndirectLod[stageNum], IndirectLinear[stageNum], texmap,
|
IndirectLod[stageNum], IndirectLinear[stageNum], texmap,
|
||||||
IndirectTex[stageNum]);
|
IndirectTex[stageNum]);
|
||||||
|
|
||||||
#if ALLOW_TEV_DUMPS
|
|
||||||
if (g_ActiveConfig.bDumpTevStages)
|
|
||||||
{
|
|
||||||
u8 stage[4] = {IndirectTex[stageNum][TextureSampler::ALP_SMP],
|
|
||||||
IndirectTex[stageNum][TextureSampler::BLU_SMP],
|
|
||||||
IndirectTex[stageNum][TextureSampler::GRN_SMP], 255};
|
|
||||||
DebugUtil::DrawTempBuffer(stage, INDIRECT + stageNum);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned int stageNum = 0; stageNum <= bpmem.genMode.numtevstages; stageNum++)
|
for (unsigned int stageNum = 0; stageNum <= bpmem.genMode.numtevstages; stageNum++)
|
||||||
|
@ -478,11 +467,6 @@ void Tev::Draw()
|
||||||
std::memset(texel, 0, 4);
|
std::memset(texel, 0, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ALLOW_TEV_DUMPS
|
|
||||||
if (g_ActiveConfig.bDumpTevTextureFetches)
|
|
||||||
DebugUtil::DrawTempBuffer(texel, DIRECT_TFETCH + stageNum);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const auto& swap = bpmem.tevksel.GetSwapTable(ac.tswap);
|
const auto& swap = bpmem.tevksel.GetSwapTable(ac.tswap);
|
||||||
TexColor.r = texel[u32(swap[ColorChannel::Red])];
|
TexColor.r = texel[u32(swap[ColorChannel::Red])];
|
||||||
TexColor.g = texel[u32(swap[ColorChannel::Green])];
|
TexColor.g = texel[u32(swap[ColorChannel::Green])];
|
||||||
|
@ -547,15 +531,6 @@ void Tev::Draw()
|
||||||
Reg[ac.dest].a = Clamp255(Reg[ac.dest].a);
|
Reg[ac.dest].a = Clamp255(Reg[ac.dest].a);
|
||||||
else
|
else
|
||||||
Reg[ac.dest].a = Clamp1024(Reg[ac.dest].a);
|
Reg[ac.dest].a = Clamp1024(Reg[ac.dest].a);
|
||||||
|
|
||||||
#if ALLOW_TEV_DUMPS
|
|
||||||
if (g_ActiveConfig.bDumpTevStages)
|
|
||||||
{
|
|
||||||
u8 stage[4] = {(u8)Reg[cc.dest].r, (u8)Reg[cc.dest].g, (u8)Reg[cc.dest].b,
|
|
||||||
(u8)Reg[ac.dest].a};
|
|
||||||
DebugUtil::DrawTempBuffer(stage, DIRECT + stageNum);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert to 8 bits per component
|
// convert to 8 bits per component
|
||||||
|
@ -711,26 +686,6 @@ void Tev::Draw()
|
||||||
BBoxManager::Update(static_cast<u16>(Position[0] & ~1), static_cast<u16>(Position[0] | 1),
|
BBoxManager::Update(static_cast<u16>(Position[0] & ~1), static_cast<u16>(Position[0] | 1),
|
||||||
static_cast<u16>(Position[1] & ~1), static_cast<u16>(Position[1] | 1));
|
static_cast<u16>(Position[1] & ~1), static_cast<u16>(Position[1] | 1));
|
||||||
|
|
||||||
#if ALLOW_TEV_DUMPS
|
|
||||||
if (g_ActiveConfig.bDumpTevStages)
|
|
||||||
{
|
|
||||||
for (u32 i = 0; i < bpmem.genMode.numindstages; ++i)
|
|
||||||
DebugUtil::CopyTempBuffer(Position[0], Position[1], INDIRECT, i, "Indirect");
|
|
||||||
for (u32 i = 0; i <= bpmem.genMode.numtevstages; ++i)
|
|
||||||
DebugUtil::CopyTempBuffer(Position[0], Position[1], DIRECT, i, "Stage");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (g_ActiveConfig.bDumpTevTextureFetches)
|
|
||||||
{
|
|
||||||
for (u32 i = 0; i <= bpmem.genMode.numtevstages; ++i)
|
|
||||||
{
|
|
||||||
TwoTevStageOrders& order = bpmem.tevorders[i >> 1];
|
|
||||||
if (order.getEnable(i & 1))
|
|
||||||
DebugUtil::CopyTempBuffer(Position[0], Position[1], DIRECT_TFETCH, i, "TFetch");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
INCSTAT(g_stats.this_frame.tev_pixels_out);
|
INCSTAT(g_stats.this_frame.tev_pixels_out);
|
||||||
EfbInterface::IncPerfCounterQuadCount(PQ_BLEND_INPUT);
|
EfbInterface::IncPerfCounterQuadCount(PQ_BLEND_INPUT);
|
||||||
|
|
||||||
|
|
|
@ -104,12 +104,6 @@ void VideoConfig::Refresh()
|
||||||
iShaderCompilerThreads = Config::Get(Config::GFX_SHADER_COMPILER_THREADS);
|
iShaderCompilerThreads = Config::Get(Config::GFX_SHADER_COMPILER_THREADS);
|
||||||
iShaderPrecompilerThreads = Config::Get(Config::GFX_SHADER_PRECOMPILER_THREADS);
|
iShaderPrecompilerThreads = Config::Get(Config::GFX_SHADER_PRECOMPILER_THREADS);
|
||||||
|
|
||||||
bDumpObjects = Config::Get(Config::GFX_SW_DUMP_OBJECTS);
|
|
||||||
bDumpTevStages = Config::Get(Config::GFX_SW_DUMP_TEV_STAGES);
|
|
||||||
bDumpTevTextureFetches = Config::Get(Config::GFX_SW_DUMP_TEV_TEX_FETCHES);
|
|
||||||
drawStart = Config::Get(Config::GFX_SW_DRAW_START);
|
|
||||||
drawEnd = Config::Get(Config::GFX_SW_DRAW_END);
|
|
||||||
|
|
||||||
bForceFiltering = Config::Get(Config::GFX_ENHANCE_FORCE_FILTERING);
|
bForceFiltering = Config::Get(Config::GFX_ENHANCE_FORCE_FILTERING);
|
||||||
iMaxAnisotropy = Config::Get(Config::GFX_ENHANCE_MAX_ANISOTROPY);
|
iMaxAnisotropy = Config::Get(Config::GFX_ENHANCE_MAX_ANISOTROPY);
|
||||||
sPostProcessingShader = Config::Get(Config::GFX_ENHANCE_POST_SHADER);
|
sPostProcessingShader = Config::Get(Config::GFX_ENHANCE_POST_SHADER);
|
||||||
|
|
|
@ -148,13 +148,6 @@ struct VideoConfig final
|
||||||
// D3D only config, mostly to be merged into the above
|
// D3D only config, mostly to be merged into the above
|
||||||
int iAdapter = 0;
|
int iAdapter = 0;
|
||||||
|
|
||||||
// VideoSW Debugging
|
|
||||||
int drawStart = 0;
|
|
||||||
int drawEnd = 0;
|
|
||||||
bool bDumpObjects = false;
|
|
||||||
bool bDumpTevStages = false;
|
|
||||||
bool bDumpTevTextureFetches = false;
|
|
||||||
|
|
||||||
// Enable API validation layers, currently only supported with Vulkan.
|
// Enable API validation layers, currently only supported with Vulkan.
|
||||||
bool bEnableValidationLayer = false;
|
bool bEnableValidationLayer = false;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue