GPU: Implement "Scaled Dithering" option

Fixes #29.
This commit is contained in:
Connor McLaughlin 2020-03-01 00:05:31 +10:00
parent d41e6dd28f
commit 635ab72b37
14 changed files with 65 additions and 22 deletions

View File

@ -26,9 +26,11 @@ bool GPU_HW::Initialize(HostDisplay* host_display, System* system, DMA* dma, Int
if (!GPU::Initialize(host_display, system, dma, interrupt_controller, timers))
return false;
m_resolution_scale = m_system->GetSettings().gpu_resolution_scale;
m_true_color = m_system->GetSettings().gpu_true_color;
m_texture_filtering = m_system->GetSettings().gpu_texture_filtering;
const Settings& settings = m_system->GetSettings();
m_resolution_scale = settings.gpu_resolution_scale;
m_true_color = settings.gpu_true_color;
m_scaled_dithering = settings.gpu_scaled_dithering;
m_texture_filtering = settings.gpu_texture_filtering;
if (m_resolution_scale < 1 || m_resolution_scale > m_max_resolution_scale)
{
m_system->GetHostInterface()->AddFormattedOSDMessage(5.0f, "Invalid resolution scale %ux specified. Maximum is %u.",
@ -68,9 +70,11 @@ void GPU_HW::UpdateSettings()
{
GPU::UpdateSettings();
m_resolution_scale = std::clamp<u32>(m_system->GetSettings().gpu_resolution_scale, 1, m_max_resolution_scale);
m_true_color = m_system->GetSettings().gpu_true_color;
m_texture_filtering = m_system->GetSettings().gpu_texture_filtering;
const Settings& settings = m_system->GetSettings();
m_resolution_scale = std::clamp<u32>(settings.gpu_resolution_scale, 1, m_max_resolution_scale);
m_true_color = settings.gpu_true_color;
m_scaled_dithering = settings.gpu_scaled_dithering;
m_texture_filtering = settings.gpu_texture_filtering;
}
void GPU_HW::LoadVertices(RenderCommand rc, u32 num_vertices, const u32* command_ptr)

View File

@ -161,7 +161,8 @@ protected:
u32 m_resolution_scale = 1;
u32 m_max_resolution_scale = 1;
bool m_true_color = false;
bool m_true_color = true;
bool m_scaled_dithering = false;
bool m_texture_filtering = false;
bool m_supports_dual_source_blend = false;

View File

@ -242,8 +242,8 @@ bool GPU_HW_D3D11::CreateBatchInputLayout()
{"ATTR", 3, DXGI_FORMAT_R32_SINT, 0, offsetof(BatchVertex, texpage), D3D11_INPUT_PER_VERTEX_DATA, 0}}};
// we need a vertex shader...
GPU_HW_ShaderGen shadergen(m_host_display->GetRenderAPI(), m_resolution_scale, m_true_color, m_texture_filtering,
m_supports_dual_source_blend);
GPU_HW_ShaderGen shadergen(m_host_display->GetRenderAPI(), m_resolution_scale, m_true_color, m_scaled_dithering,
m_texture_filtering, m_supports_dual_source_blend);
ComPtr<ID3DBlob> vs_bytecode =
m_shader_cache.GetShaderBlob(D3D11::ShaderCompiler::Type::Vertex, shadergen.GenerateBatchVertexShader(true));
if (!vs_bytecode)
@ -325,8 +325,8 @@ bool GPU_HW_D3D11::CreateStateObjects()
bool GPU_HW_D3D11::CompileShaders()
{
GPU_HW_ShaderGen shadergen(m_host_display->GetRenderAPI(), m_resolution_scale, m_true_color, m_texture_filtering,
m_supports_dual_source_blend);
GPU_HW_ShaderGen shadergen(m_host_display->GetRenderAPI(), m_resolution_scale, m_true_color, m_scaled_dithering,
m_texture_filtering, m_supports_dual_source_blend);
m_system->GetHostInterface()->DisplayLoadingScreen("Compiling shaders...");

View File

@ -290,8 +290,8 @@ bool GPU_HW_OpenGL::CreateTextureBuffer()
bool GPU_HW_OpenGL::CompilePrograms()
{
GPU_HW_ShaderGen shadergen(m_host_display->GetRenderAPI(), m_resolution_scale, m_true_color, m_texture_filtering,
m_supports_dual_source_blend);
GPU_HW_ShaderGen shadergen(m_host_display->GetRenderAPI(), m_resolution_scale, m_true_color, m_scaled_dithering,
m_texture_filtering, m_supports_dual_source_blend);
m_system->GetHostInterface()->DisplayLoadingScreen("Compiling Shaders...");

View File

@ -188,8 +188,8 @@ void GPU_HW_OpenGL_ES::ClearFramebuffer()
bool GPU_HW_OpenGL_ES::CompilePrograms()
{
GPU_HW_ShaderGen shadergen(m_host_display->GetRenderAPI(), m_resolution_scale, m_true_color, m_texture_filtering,
m_supports_dual_source_blend);
GPU_HW_ShaderGen shadergen(m_host_display->GetRenderAPI(), m_resolution_scale, m_true_color, m_scaled_dithering,
m_texture_filtering, m_supports_dual_source_blend);
for (u32 render_mode = 0; render_mode < 4; render_mode++)
{

View File

@ -6,10 +6,11 @@
Log_SetChannel(GPU_HW_ShaderGen);
GPU_HW_ShaderGen::GPU_HW_ShaderGen(HostDisplay::RenderAPI render_api, u32 resolution_scale, bool true_color,
bool texture_filtering, bool supports_dual_source_blend)
bool scaled_dithering, bool texture_filtering, bool supports_dual_source_blend)
: m_render_api(render_api), m_resolution_scale(resolution_scale), m_true_color(true_color),
m_texture_filering(texture_filtering), m_glsl(render_api != HostDisplay::RenderAPI::D3D11),
m_glsl_es(render_api == HostDisplay::RenderAPI::OpenGLES), m_supports_dual_source_blend(supports_dual_source_blend)
m_scaled_dithering(scaled_dithering), m_texture_filering(texture_filtering),
m_glsl(render_api != HostDisplay::RenderAPI::D3D11), m_glsl_es(render_api == HostDisplay::RenderAPI::OpenGLES),
m_supports_dual_source_blend(supports_dual_source_blend)
{
if (m_glsl)
SetGLSLVersionString();
@ -411,6 +412,7 @@ std::string GPU_HW_ShaderGen::GenerateBatchFragmentShader(GPU_HW::BatchRenderMod
DefineMacro(ss, "PALETTE_8_BIT", actual_texture_mode == GPU::TextureMode::Palette8Bit);
DefineMacro(ss, "RAW_TEXTURE", raw_texture);
DefineMacro(ss, "DITHERING", dithering);
DefineMacro(ss, "DITHERING_SCALED", m_scaled_dithering);
DefineMacro(ss, "TRUE_COLOR", m_true_color);
DefineMacro(ss, "TEXTURE_FILTERING", m_texture_filering);
DefineMacro(ss, "USE_DUAL_SOURCE", use_dual_source);
@ -570,7 +572,11 @@ float4 SampleFromVRAM(int4 texpage, int2 icoord)
// Apply dithering
#if DITHERING
icolor = ApplyDithering(int2(v_pos.xy) / int2(RESOLUTION_SCALE, RESOLUTION_SCALE), icolor);
#if DITHERING_SCALED
icolor = ApplyDithering(int2(v_pos.xy), icolor);
#else
icolor = ApplyDithering(int2(v_pos.xy) / int2(RESOLUTION_SCALE, RESOLUTION_SCALE), icolor);
#endif
#endif
// Clip to 15-bit range

View File

@ -7,7 +7,7 @@
class GPU_HW_ShaderGen
{
public:
GPU_HW_ShaderGen(HostDisplay::RenderAPI render_api, u32 resolution_scale, bool true_color,
GPU_HW_ShaderGen(HostDisplay::RenderAPI render_api, u32 resolution_scale, bool true_color, bool scaled_dithering,
bool texture_filtering, bool supports_dual_source_belnd);
~GPU_HW_ShaderGen();
@ -25,6 +25,7 @@ public:
HostDisplay::RenderAPI m_render_api;
u32 m_resolution_scale;
bool m_true_color;
bool m_scaled_dithering;
bool m_texture_filering;
bool m_glsl;
bool m_glsl_es;

View File

@ -812,6 +812,7 @@ void HostInterface::SetDefaultSettings(SettingsInterface& si)
si.SetStringValue("GPU", "Renderer", Settings::GetRendererName(Settings::DEFAULT_GPU_RENDERER));
si.SetIntValue("GPU", "ResolutionScale", 1);
si.SetBoolValue("GPU", "TrueColor", true);
si.SetBoolValue("GPU", "ScaledDithering", false);
si.SetBoolValue("GPU", "TextureFiltering", false);
si.SetBoolValue("GPU", "UseDebugDevice", false);
@ -855,6 +856,7 @@ void HostInterface::UpdateSettings(const std::function<void()>& apply_callback)
const GPURenderer old_gpu_renderer = m_settings.gpu_renderer;
const u32 old_gpu_resolution_scale = m_settings.gpu_resolution_scale;
const bool old_gpu_true_color = m_settings.gpu_true_color;
const bool old_gpu_scaled_dithering = m_settings.gpu_scaled_dithering;
const bool old_gpu_texture_filtering = m_settings.gpu_texture_filtering;
const bool old_display_force_progressive_scan = m_settings.display_force_progressive_scan;
const bool old_gpu_debug_device = m_settings.gpu_use_debug_device;
@ -907,6 +909,7 @@ void HostInterface::UpdateSettings(const std::function<void()>& apply_callback)
if (m_settings.gpu_resolution_scale != old_gpu_resolution_scale ||
m_settings.gpu_true_color != old_gpu_true_color ||
m_settings.gpu_scaled_dithering != old_gpu_scaled_dithering ||
m_settings.gpu_texture_filtering != old_gpu_texture_filtering ||
m_settings.display_force_progressive_scan != old_display_force_progressive_scan ||
m_settings.display_crop_mode != old_display_crop_mode)

View File

@ -22,7 +22,8 @@ void Settings::Load(SettingsInterface& si)
gpu_renderer = ParseRendererName(si.GetStringValue("GPU", "Renderer", GetRendererName(DEFAULT_GPU_RENDERER)).c_str())
.value_or(DEFAULT_GPU_RENDERER);
gpu_resolution_scale = static_cast<u32>(si.GetIntValue("GPU", "ResolutionScale", 1));
gpu_true_color = si.GetBoolValue("GPU", "TrueColor", false);
gpu_true_color = si.GetBoolValue("GPU", "TrueColor", true);
gpu_scaled_dithering = si.GetBoolValue("GPU", "ScaledDithering", false);
gpu_texture_filtering = si.GetBoolValue("GPU", "TextureFiltering", false);
gpu_use_debug_device = si.GetBoolValue("GPU", "UseDebugDevice", false);
@ -78,6 +79,7 @@ void Settings::Save(SettingsInterface& si) const
si.SetStringValue("GPU", "Renderer", GetRendererName(gpu_renderer));
si.SetIntValue("GPU", "ResolutionScale", static_cast<long>(gpu_resolution_scale));
si.SetBoolValue("GPU", "TrueColor", gpu_true_color);
si.SetBoolValue("GPU", "ScaledDithering", gpu_scaled_dithering);
si.SetBoolValue("GPU", "TextureFiltering", gpu_texture_filtering);
si.SetBoolValue("GPU", "UseDebugDevice", gpu_use_debug_device);

View File

@ -46,7 +46,8 @@ struct Settings
GPURenderer gpu_renderer = GPURenderer::Software;
u32 gpu_resolution_scale = 1;
bool gpu_true_color = false;
bool gpu_true_color = true;
bool gpu_scaled_dithering = false;
bool gpu_texture_filtering = false;
bool gpu_use_debug_device = false;
DisplayCropMode display_crop_mode = DisplayCropMode::None;

View File

@ -22,11 +22,25 @@ GPUSettingsWidget::GPUSettingsWidget(QtHostInterface* host_interface, QWidget* p
SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.vsync, "Display/VSync");
SettingWidgetBinder::BindWidgetToIntSetting(m_host_interface, m_ui.resolutionScale, "GPU/ResolutionScale");
SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.trueColor, "GPU/TrueColor");
SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.scaledDithering, "GPU/ScaledDithering");
SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.linearTextureFiltering, "GPU/TextureFiltering");
connect(m_ui.resolutionScale, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
&GPUSettingsWidget::updateScaledDitheringEnabled);
connect(m_ui.trueColor, &QCheckBox::stateChanged, this, &GPUSettingsWidget::updateScaledDitheringEnabled);
updateScaledDitheringEnabled();
}
GPUSettingsWidget::~GPUSettingsWidget() = default;
void GPUSettingsWidget::updateScaledDitheringEnabled()
{
const int resolution_scale = m_ui.resolutionScale->currentIndex();
const bool true_color = m_ui.trueColor->isChecked();
const bool allow_scaled_dithering = (resolution_scale != 1 && !true_color);
m_ui.scaledDithering->setEnabled(allow_scaled_dithering);
}
void GPUSettingsWidget::setupAdditionalUi()
{
for (u32 i = 0; i < static_cast<u32>(GPURenderer::Count); i++)

View File

@ -14,6 +14,9 @@ public:
GPUSettingsWidget(QtHostInterface* host_interface, QWidget* parent = nullptr);
~GPUSettingsWidget();
private Q_SLOTS:
void updateScaledDitheringEnabled();
private:
void setupAdditionalUi();

View File

@ -123,6 +123,13 @@
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QCheckBox" name="scaledDithering">
<property name="text">
<string>Scaled Dithering (scale dither pattern to resolution)</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QCheckBox" name="linearTextureFiltering">
<property name="text">
<string>Bilinear Texture Filtering</string>

View File

@ -885,6 +885,7 @@ void SDLHostInterface::DrawQuickSettingsMenu()
}
settings_changed |= ImGui::MenuItem("True (24-Bit) Color", nullptr, &m_settings_copy.gpu_true_color);
settings_changed |= ImGui::MenuItem("Scaled Dithering", nullptr, &m_settings_copy.gpu_scaled_dithering);
settings_changed |= ImGui::MenuItem("Texture Filtering", nullptr, &m_settings_copy.gpu_texture_filtering);
settings_changed |= ImGui::MenuItem("Display Linear Filtering", nullptr, &m_settings_copy.display_linear_filtering);