This commit is contained in:
Connor McLaughlin 2020-11-02 21:45:46 +10:00
parent a04490d569
commit 1298246ed7
13 changed files with 172 additions and 26 deletions

View File

@ -72,6 +72,7 @@ public:
virtual bool CreateResources() = 0;
virtual void DestroyResources() = 0;
virtual bool SetScalingShader(const std::string_view& config) = 0;
virtual bool SetPostProcessingChain(const std::string_view& config) = 0;
/// Call when the window size changes externally to recreate any resources.

View File

@ -461,6 +461,7 @@ void HostInterface::SetDefaultSettings(SettingsInterface& si)
si.SetBoolValue("Display", "ShowResolution", false);
si.SetBoolValue("Display", "Fullscreen", false);
si.SetBoolValue("Display", "VSync", true);
si.SetStringValue("Display", "ScaleShader", "");
si.SetStringValue("Display", "PostProcessChain", "");
si.SetBoolValue("CDROM", "ReadThread", true);

View File

@ -175,6 +175,7 @@ void Settings::Load(SettingsInterface& si)
display_show_speed = si.GetBoolValue("Display", "ShowSpeed", false);
display_show_resolution = si.GetBoolValue("Display", "ShowResolution", false);
video_sync_enabled = si.GetBoolValue("Display", "VSync", true);
display_scale_shader = si.GetStringValue("Display", "ScaleShader", "");
display_post_process_chain = si.GetStringValue("Display", "PostProcessChain", "");
cdrom_read_thread = si.GetBoolValue("CDROM", "ReadThread", true);
@ -298,6 +299,11 @@ void Settings::Save(SettingsInterface& si) const
si.SetBoolValue("Display", "ShowSpeed", display_show_speed);
si.SetBoolValue("Display", "ShowResolution", display_show_speed);
si.SetBoolValue("Display", "VSync", video_sync_enabled);
if (display_scale_shader.empty())
si.DeleteValue("Display", "ScaleShader");
else
si.SetStringValue("Display", "ScaleShader", display_scale_shader.c_str());
if (display_post_process_chain.empty())
si.DeleteValue("Display", "PostProcessChain");
else

View File

@ -91,6 +91,7 @@ struct Settings
GPURenderer gpu_renderer = GPURenderer::Software;
std::string gpu_adapter;
std::string display_scale_shader;
std::string display_post_process_chain;
u32 gpu_resolution_scale = 1;
u32 gpu_multisamples = 1;

View File

@ -177,6 +177,7 @@ void CommonHostInterface::DestroySystem()
SetTimerResolutionIncreased(false);
m_save_state_selector_ui->Close();
m_display->SetPostProcessingChain({});
m_display->SetScalingShader({});
HostInterface::DestroySystem();
}
@ -715,6 +716,9 @@ void CommonHostInterface::OnSystemCreated()
{
HostInterface::OnSystemCreated();
if (!g_settings.display_scale_shader.empty() && !m_display->SetScalingShader(g_settings.display_scale_shader))
AddOSDMessage(TranslateStdString("OSDMessage", "Failed to load scaling shader."), 20.0f);
if (g_settings.display_post_processing && !m_display->SetPostProcessingChain(g_settings.display_post_process_chain))
AddOSDMessage(TranslateStdString("OSDMessage", "Failed to load post processing shader chain."), 20.0f);
}
@ -2082,6 +2086,12 @@ void CommonHostInterface::CheckForSettingsChanges(const Settings& old_settings)
UpdateSpeedLimiterState();
}
if (g_settings.display_scale_shader != old_settings.display_scale_shader)
{
if (!m_display->SetScalingShader(g_settings.display_post_process_chain))
AddOSDMessage(TranslateStdString("OSDMessage", "Failed to load scaling shader."), 20.0f);
}
if (g_settings.display_post_processing != old_settings.display_post_processing ||
g_settings.display_post_process_chain != old_settings.display_post_process_chain)
{
@ -2469,13 +2479,24 @@ void CommonHostInterface::TogglePostProcessing()
void CommonHostInterface::ReloadPostProcessingShaders()
{
if (!m_display || !g_settings.display_post_processing)
if (!m_display)
return;
if (!m_display->SetPostProcessingChain(g_settings.display_post_process_chain))
AddOSDMessage(TranslateStdString("OSDMessage", "Failed to load post-processing shader chain."), 20.0f);
else
AddOSDMessage(TranslateStdString("OSDMessage", "Post-processing shaders reloaded."), 10.0f);
if (!g_settings.display_scale_shader.empty())
{
if (!m_display->SetScalingShader(g_settings.display_scale_shader))
AddOSDMessage(TranslateStdString("OSDMessage", "Failed to load scaling shader."), 20.0f);
else
AddOSDMessage(TranslateStdString("OSDMessage", "Scaling shader reloaded."), 10.0f);
}
if (g_settings.display_post_processing)
{
if (!m_display->SetPostProcessingChain(g_settings.display_post_process_chain))
AddOSDMessage(TranslateStdString("OSDMessage", "Failed to load post-processing shader chain."), 20.0f);
else
AddOSDMessage(TranslateStdString("OSDMessage", "Post-processing shaders reloaded."), 10.0f);
}
}
bool CommonHostInterface::ParseFullscreenMode(const std::string_view& mode, u32* width, u32* height,

View File

@ -724,19 +724,38 @@ void D3D11HostDisplay::RenderDisplay(s32 left, s32 top, s32 width, s32 height, v
s32 texture_view_height, bool linear_filter)
{
m_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
m_context->VSSetShader(m_display_vertex_shader.Get(), nullptr, 0);
m_context->PSSetShader(m_display_pixel_shader.Get(), nullptr, 0);
m_context->PSSetShaderResources(0, 1, reinterpret_cast<ID3D11ShaderResourceView**>(&texture_handle));
m_context->PSSetSamplers(0, 1, linear_filter ? m_linear_sampler.GetAddressOf() : m_point_sampler.GetAddressOf());
m_context->PSSetSamplers(0, 1,
(linear_filter && !m_scale_stage.has_value()) ? m_linear_sampler.GetAddressOf() :
m_point_sampler.GetAddressOf());
if (!m_scale_stage)
{
const float uniforms[4] = {static_cast<float>(texture_view_x) / static_cast<float>(texture_width),
static_cast<float>(texture_view_y) / static_cast<float>(texture_height),
(static_cast<float>(texture_view_width) - 0.5f) / static_cast<float>(texture_width),
(static_cast<float>(texture_view_height) - 0.5f) / static_cast<float>(texture_height)};
const auto map =
m_display_uniform_buffer.Map(m_context.Get(), m_display_uniform_buffer.GetSize(), sizeof(uniforms));
std::memcpy(map.pointer, uniforms, sizeof(uniforms));
m_display_uniform_buffer.Unmap(m_context.Get(), sizeof(uniforms));
m_context->VSSetShader(m_display_vertex_shader.Get(), nullptr, 0);
m_context->VSSetConstantBuffers(0, 1, m_display_uniform_buffer.GetD3DBufferArray());
m_context->PSSetShader(m_display_pixel_shader.Get(), nullptr, 0);
}
else
{
const auto map =
m_display_uniform_buffer.Map(m_context.Get(), m_display_uniform_buffer.GetSize(), m_scale_stage->uniforms_size);
m_scale_shader->FillUniformBuffer(map.pointer, texture_width, texture_height, texture_view_x, texture_view_y,
texture_view_width, texture_view_height, width, height, 0.0f);
m_display_uniform_buffer.Unmap(m_context.Get(), m_scale_stage->uniforms_size);
m_context->VSSetShader(m_scale_stage->vertex_shader.Get(), nullptr, 0);
m_context->VSSetConstantBuffers(0, 1, m_display_uniform_buffer.GetD3DBufferArray());
m_context->PSSetShader(m_scale_stage->pixel_shader.Get(), nullptr, 0);
m_context->PSSetConstantBuffers(0, 1, m_display_uniform_buffer.GetD3DBufferArray());
}
const float uniforms[4] = {static_cast<float>(texture_view_x) / static_cast<float>(texture_width),
static_cast<float>(texture_view_y) / static_cast<float>(texture_height),
(static_cast<float>(texture_view_width) - 0.5f) / static_cast<float>(texture_width),
(static_cast<float>(texture_view_height) - 0.5f) / static_cast<float>(texture_height)};
const auto map = m_display_uniform_buffer.Map(m_context.Get(), m_display_uniform_buffer.GetSize(), sizeof(uniforms));
std::memcpy(map.pointer, uniforms, sizeof(uniforms));
m_display_uniform_buffer.Unmap(m_context.Get(), sizeof(uniforms));
m_context->VSSetConstantBuffers(0, 1, m_display_uniform_buffer.GetD3DBufferArray());
const CD3D11_VIEWPORT vp(static_cast<float>(left), static_cast<float>(top), static_cast<float>(width),
static_cast<float>(height));
@ -862,6 +881,43 @@ D3D11HostDisplay::AdapterInfo D3D11HostDisplay::GetAdapterInfo(IDXGIFactory* dxg
return adapter_info;
}
bool D3D11HostDisplay::SetScalingShader(const std::string_view& config)
{
if (config.empty())
{
m_scale_shader.reset();
m_scale_stage.reset();
return true;
}
m_scale_shader = PostProcessingShader();
if (!PostProcessingChain::CreateSingleShader(&m_scale_shader.value(), config))
{
m_scale_shader.reset();
return false;
}
m_scale_stage = PostProcessingStage();
if (!CompilePostProcessingStage(m_scale_shader.value(), &m_scale_stage.value()))
{
Log_ErrorPrintf("Failed to compile resize shader");
m_scale_stage.reset();
m_scale_shader.reset();
return false;
}
if (m_display_uniform_buffer.GetSize() < m_scale_stage->uniforms_size &&
!m_display_uniform_buffer.Create(m_device.Get(), D3D11_BIND_CONSTANT_BUFFER, m_scale_stage->uniforms_size))
{
Log_ErrorPrintf("Failed to allocate %u byte constant buffer for scaling", m_scale_stage->uniforms_size);
m_scale_stage.reset();
m_scale_shader.reset();
return false;
}
return true;
}
bool D3D11HostDisplay::SetPostProcessingChain(const std::string_view& config)
{
if (config.empty())
@ -882,17 +938,10 @@ bool D3D11HostDisplay::SetPostProcessingChain(const std::string_view& config)
for (u32 i = 0; i < m_post_processing_chain.GetStageCount(); i++)
{
const PostProcessingShader& shader = m_post_processing_chain.GetShaderStage(i);
const std::string vs = shadergen.GeneratePostProcessingVertexShader(shader);
const std::string ps = shadergen.GeneratePostProcessingFragmentShader(shader);
PostProcessingStage stage;
stage.uniforms_size = shader.GetUniformsSize();
stage.vertex_shader =
D3D11::ShaderCompiler::CompileAndCreateVertexShader(m_device.Get(), vs, g_settings.gpu_use_debug_device);
stage.pixel_shader =
D3D11::ShaderCompiler::CompileAndCreatePixelShader(m_device.Get(), ps, g_settings.gpu_use_debug_device);
if (!stage.vertex_shader || !stage.pixel_shader)
const PostProcessingShader& shader = m_post_processing_chain.GetShaderStage(i);
if (!CompilePostProcessingStage(shader, &stage))
{
Log_ErrorPrintf("Failed to compile one or more post-processing shaders, disabling.");
m_post_processing_stages.clear();
@ -944,6 +993,21 @@ bool D3D11HostDisplay::CheckPostProcessingRenderTargets(u32 target_width, u32 ta
return true;
}
bool D3D11HostDisplay::CompilePostProcessingStage(const PostProcessingShader& shader, PostProcessingStage* stage)
{
FrontendCommon::PostProcessingShaderGen shadergen(HostDisplay::RenderAPI::D3D11, true);
const std::string vs = shadergen.GeneratePostProcessingVertexShader(shader);
const std::string ps = shadergen.GeneratePostProcessingFragmentShader(shader);
stage->uniforms_size = shader.GetUniformsSize();
stage->vertex_shader =
D3D11::ShaderCompiler::CompileAndCreateVertexShader(m_device.Get(), vs, g_settings.gpu_use_debug_device);
stage->pixel_shader =
D3D11::ShaderCompiler::CompileAndCreatePixelShader(m_device.Get(), ps, g_settings.gpu_use_debug_device);
return stage->vertex_shader && stage->pixel_shader;
}
void D3D11HostDisplay::ApplyPostProcessingChain(ID3D11RenderTargetView* final_target, s32 final_left, s32 final_top,
s32 final_width, s32 final_height, void* texture_handle,
u32 texture_width, s32 texture_height, s32 texture_view_x,
@ -1013,6 +1077,11 @@ void D3D11HostDisplay::ApplyPostProcessingChain(ID3D11RenderTargetView* final_ta
#else // LIBRETRO
bool D3D11HostDisplay::SetScalingShader(const std::string_view& config)
{
return false;
}
bool D3D11HostDisplay::SetPostProcessingChain(const std::string_view& config)
{
return false;

View File

@ -8,6 +8,7 @@
#include <d3d11.h>
#include <dxgi.h>
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <vector>
@ -49,6 +50,7 @@ public:
virtual bool SetFullscreen(bool fullscreen, u32 width, u32 height, float refresh_rate) override;
virtual void DestroyRenderSurface() override;
virtual bool SetScalingShader(const std::string_view& config) override;
virtual bool SetPostProcessingChain(const std::string_view& config) override;
std::unique_ptr<HostDisplayTexture> CreateTexture(u32 width, u32 height, const void* initial_data,
@ -108,6 +110,7 @@ protected:
};
bool CheckPostProcessingRenderTargets(u32 target_width, u32 target_height);
bool CompilePostProcessingStage(const PostProcessingShader& shader, PostProcessingStage* stage);
void ApplyPostProcessingChain(ID3D11RenderTargetView* final_target, s32 final_left, s32 final_top, s32 final_width,
s32 final_height, void* texture_handle, u32 texture_width, s32 texture_height,
s32 texture_view_x, s32 texture_view_y, s32 texture_view_width,
@ -142,6 +145,8 @@ protected:
bool m_using_allow_tearing = false;
bool m_vsync = true;
std::optional<PostProcessingShader> m_scale_shader;
std::optional<PostProcessingStage> m_scale_stage;
PostProcessingChain m_post_processing_chain;
D3D11::Texture m_post_processing_input_texture;
std::vector<PostProcessingStage> m_post_processing_stages;

View File

@ -572,6 +572,11 @@ void OpenGLHostDisplay::RenderSoftwareCursor(s32 left, s32 bottom, s32 width, s3
#ifndef LIBRETRO
bool OpenGLHostDisplay::SetScalingShader(const std::string_view& config)
{
return false;
}
bool OpenGLHostDisplay::SetPostProcessingChain(const std::string_view& config)
{
if (config.empty())
@ -742,6 +747,11 @@ void OpenGLHostDisplay::ApplyPostProcessingChain(GLuint final_target, s32 final_
#else
bool OpenGLHostDisplay::SetScalingShader(const std::string_view& config)
{
return false;
}
bool OpenGLHostDisplay::SetPostProcessingChain(const std::string_view& config)
{
return false;

View File

@ -49,6 +49,7 @@ public:
virtual bool SetFullscreen(bool fullscreen, u32 width, u32 height, float refresh_rate) override;
virtual void DestroyRenderSurface() override;
virtual bool SetScalingShader(const std::string_view& config) override;
virtual bool SetPostProcessingChain(const std::string_view& config) override;
std::unique_ptr<HostDisplayTexture> CreateTexture(u32 width, u32 height, const void* initial_data,

View File

@ -128,6 +128,25 @@ bool PostProcessingChain::CreateFromString(const std::string_view& chain_config)
return true;
}
bool PostProcessingChain::CreateSingleShader(PostProcessingShader* shader, const std::string_view& shader_config)
{
size_t first_shader_sep = shader_config.find(';');
if (first_shader_sep == std::string::npos)
first_shader_sep = shader_config.size();
const std::string_view shader_name = shader_config.substr(0, first_shader_sep);
if (shader_name.empty())
return false;
if (!TryLoadingShader(shader, shader_name))
return false;
if (first_shader_sep < shader_config.size())
shader->SetConfigString(shader_config.substr(first_shader_sep + 1));
return true;
}
std::vector<std::string> PostProcessingChain::GetAvailableShaderNames()
{
std::vector<std::string> names;

View File

@ -28,6 +28,7 @@ public:
bool CreateFromString(const std::string_view& chain_config);
static std::vector<std::string> GetAvailableShaderNames();
static bool CreateSingleShader(PostProcessingShader* shader, const std::string_view& shader_config);
private:
std::vector<PostProcessingShader> m_shaders;

View File

@ -750,6 +750,11 @@ VulkanHostDisplay::PostProcessingStage::~PostProcessingStage()
g_vulkan_context->DeferPipelineDestruction(pipeline);
}
bool VulkanHostDisplay::SetScalingShader(const std::string_view& config)
{
return false;
}
bool VulkanHostDisplay::SetPostProcessingChain(const std::string_view& config)
{
g_vulkan_context->ExecuteCommandBuffer(true);
@ -991,6 +996,11 @@ void VulkanHostDisplay::ApplyPostProcessingChain(s32 final_left, s32 final_top,
#else // LIBRETRO
bool VulkanHostDisplay::SetScalingShader(const std::string_view& config)
{
return false;
}
bool VulkanHostDisplay::SetPostProcessingChain(const std::string_view& config)
{
return false;

View File

@ -46,6 +46,7 @@ public:
virtual bool SetFullscreen(bool fullscreen, u32 width, u32 height, float refresh_rate) override;
virtual void DestroyRenderSurface() override;
virtual bool SetScalingShader(const std::string_view& config) override;
virtual bool SetPostProcessingChain(const std::string_view& config) override;
std::unique_ptr<HostDisplayTexture> CreateTexture(u32 width, u32 height, const void* initial_data,