GPU/HW: Expose depth buffer to internal postprocessing

This commit is contained in:
Stenzek
2024-03-24 19:49:16 +10:00
parent e39a2d00bf
commit 34d5cdec96
14 changed files with 288 additions and 85 deletions

View File

@ -396,6 +396,7 @@ void PostProcessing::Chain::LoadStages()
SettingsInterface& si = GetLoadSettingsInterface(m_section);
m_enabled = si.GetBoolValue(m_section, "Enabled", false);
m_wants_depth_buffer = false;
const u32 stage_count = Config::GetStageCount(si, m_section);
if (stage_count == 0)
@ -441,6 +442,13 @@ void PostProcessing::Chain::LoadStages()
CheckTargets(g_gpu_device->GetWindowFormat(), g_gpu_device->GetWindowWidth(), g_gpu_device->GetWindowHeight(),
&progress);
}
// must be down here, because we need to compile first, triggered by CheckTargets()
for (std::unique_ptr<Shader>& shader : m_stages)
m_wants_depth_buffer |= shader->WantsDepthBuffer();
m_needs_depth_buffer = m_enabled && m_wants_depth_buffer;
if (m_wants_depth_buffer)
DEV_LOG("Depth buffer is needed.");
}
void PostProcessing::Chain::ClearStages()
@ -469,6 +477,7 @@ void PostProcessing::Chain::UpdateSettings(std::unique_lock<std::mutex>& setting
progress.SetProgressRange(stage_count);
const GPUTexture::Format prev_format = m_target_format;
m_wants_depth_buffer = false;
for (u32 i = 0; i < stage_count; i++)
{
@ -516,6 +525,13 @@ void PostProcessing::Chain::UpdateSettings(std::unique_lock<std::mutex>& setting
s_timer.Reset();
DEV_LOG("Loaded {} post-processing stages.", stage_count);
}
// must be down here, because we need to compile first, triggered by CheckTargets()
for (std::unique_ptr<Shader>& shader : m_stages)
m_wants_depth_buffer |= shader->WantsDepthBuffer();
m_needs_depth_buffer = m_enabled && m_wants_depth_buffer;
if (m_wants_depth_buffer)
DEV_LOG("Depth buffer is needed.");
}
void PostProcessing::Chain::Toggle()
@ -534,12 +550,13 @@ void PostProcessing::Chain::Toggle()
TRANSLATE_STR("OSDMessage", "Post-processing is now disabled."),
Host::OSD_QUICK_DURATION);
m_enabled = new_enabled;
m_needs_depth_buffer = new_enabled && m_wants_depth_buffer;
if (m_enabled)
s_timer.Reset();
}
bool PostProcessing::Chain::CheckTargets(GPUTexture::Format target_format, u32 target_width, u32 target_height,
ProgressCallback* progress)
ProgressCallback* progress /* = nullptr */)
{
if (m_target_format == target_format && m_target_width == target_width && m_target_height == target_height)
return true;
@ -562,6 +579,8 @@ bool PostProcessing::Chain::CheckTargets(GPUTexture::Format target_format, u32 t
progress->SetProgressRange(static_cast<u32>(m_stages.size()));
progress->SetProgressValue(0);
m_wants_depth_buffer = false;
for (size_t i = 0; i < m_stages.size(); i++)
{
Shader* const shader = m_stages[i].get();
@ -580,11 +599,13 @@ bool PostProcessing::Chain::CheckTargets(GPUTexture::Format target_format, u32 t
}
progress->SetProgressValue(static_cast<u32>(i + 1));
m_wants_depth_buffer |= shader->WantsDepthBuffer();
}
m_target_format = target_format;
m_target_width = target_width;
m_target_height = target_height;
m_needs_depth_buffer = m_enabled && m_wants_depth_buffer;
return true;
}
@ -598,21 +619,24 @@ void PostProcessing::Chain::DestroyTextures()
g_gpu_device->RecycleTexture(std::move(m_input_texture));
}
bool PostProcessing::Chain::Apply(GPUTexture* input_color, GPUTexture* final_target, s32 final_left, s32 final_top,
s32 final_width, s32 final_height, s32 orig_width, s32 orig_height, s32 native_width,
s32 native_height)
bool PostProcessing::Chain::Apply(GPUTexture* input_color, GPUTexture* input_depth, GPUTexture* final_target,
s32 final_left, s32 final_top, s32 final_width, s32 final_height, s32 orig_width,
s32 orig_height, s32 native_width, s32 native_height)
{
GL_SCOPE_FMT("{} Apply", m_section);
GPUTexture* output = m_output_texture.get();
input_color->MakeReadyForSampling();
if (input_depth)
input_depth->MakeReadyForSampling();
for (const std::unique_ptr<Shader>& stage : m_stages)
{
const bool is_final = (stage.get() == m_stages.back().get());
if (!stage->Apply(input_color, is_final ? final_target : output, final_left, final_top, final_width, final_height,
orig_width, orig_height, native_width, native_height, m_target_width, m_target_height))
if (!stage->Apply(input_color, input_depth, is_final ? final_target : output, final_left, final_top, final_width,
final_height, orig_width, orig_height, native_width, native_height, m_target_width,
m_target_height))
{
return false;
}

View File

@ -115,6 +115,7 @@ public:
~Chain();
ALWAYS_INLINE bool HasStages() const { return m_stages.empty(); }
ALWAYS_INLINE bool NeedsDepthBuffer() const { return m_needs_depth_buffer; }
ALWAYS_INLINE GPUTexture* GetInputTexture() const { return m_input_texture.get(); }
ALWAYS_INLINE GPUTexture* GetOutputTexture() const { return m_output_texture.get(); }
@ -133,8 +134,8 @@ public:
bool CheckTargets(GPUTexture::Format target_format, u32 target_width, u32 target_height,
ProgressCallback* progress = nullptr);
bool Apply(GPUTexture* input_color, GPUTexture* final_target, s32 final_left, s32 final_top, s32 final_width,
s32 final_height, s32 orig_width, s32 orig_height, s32 native_width, s32 native_height);
bool Apply(GPUTexture* input_color, GPUTexture* input_depth, GPUTexture* final_target, s32 final_left, s32 final_top,
s32 final_width, s32 final_height, s32 orig_width, s32 orig_height, s32 native_width, s32 native_height);
private:
void ClearStagesWithError(const Error& error);
@ -145,6 +146,8 @@ private:
u32 m_target_width = 0;
u32 m_target_height = 0;
bool m_enabled = false;
bool m_wants_depth_buffer = false;
bool m_needs_depth_buffer = false;
std::vector<std::unique_ptr<PostProcessing::Shader>> m_stages;
std::unique_ptr<GPUTexture> m_input_texture;

View File

@ -37,6 +37,7 @@ public:
ALWAYS_INLINE bool HasOptions() const { return !m_options.empty(); }
virtual bool IsValid() const = 0;
virtual bool WantsDepthBuffer() const = 0;
std::vector<ShaderOption> TakeOptions();
void LoadOptions(const SettingsInterface& si, const char* section);
@ -48,9 +49,9 @@ public:
virtual bool CompilePipeline(GPUTexture::Format format, u32 width, u32 height, ProgressCallback* progress) = 0;
virtual bool Apply(GPUTexture* input, GPUTexture* final_target, s32 final_left, s32 final_top, s32 final_width,
s32 final_height, s32 orig_width, s32 orig_height, s32 native_width, s32 native_height,
u32 target_width, u32 target_height) = 0;
virtual bool Apply(GPUTexture* input_color, GPUTexture* input_depth, GPUTexture* final_target, s32 final_left,
s32 final_top, s32 final_width, s32 final_height, s32 orig_width, s32 orig_height,
s32 native_width, s32 native_height, u32 target_width, u32 target_height) = 0;
protected:
static void ParseKeyValue(std::string_view line, std::string_view* key, std::string_view* value);

View File

@ -1,5 +1,4 @@
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#include "postprocessing_shader_fx.h"
@ -12,6 +11,7 @@
#include "core/settings.h"
#include "common/assert.h"
#include "common/bitutils.h"
#include "common/error.h"
#include "common/file_system.h"
#include "common/log.h"
@ -368,6 +368,11 @@ bool PostProcessing::ReShadeFXShader::IsValid() const
return m_valid;
}
bool PostProcessing::ReShadeFXShader::WantsDepthBuffer() const
{
return m_wants_depth_buffer;
}
bool PostProcessing::ReShadeFXShader::CreateModule(s32 buffer_width, s32 buffer_height, reshadefx::module* mod,
std::string code, Error* error)
{
@ -396,6 +401,10 @@ bool PostProcessing::ReShadeFXShader::CreateModule(s32 buffer_width, s32 buffer_
pp.add_macro_definition("BUFFER_RCP_WIDTH", std::to_string(1.0f / static_cast<float>(buffer_width)));
pp.add_macro_definition("BUFFER_RCP_HEIGHT", std::to_string(1.0f / static_cast<float>(buffer_height)));
pp.add_macro_definition("BUFFER_COLOR_BIT_DEPTH", "32");
pp.add_macro_definition("RESHADE_DEPTH_INPUT_IS_UPSIDE_DOWN", "0");
pp.add_macro_definition("RESHADE_DEPTH_INPUT_IS_LOGARITHMIC", "0");
pp.add_macro_definition("RESHADE_DEPTH_LINEARIZATION_FAR_PLANE", "1000.0");
pp.add_macro_definition("RESHADE_DEPTH_INPUT_IS_REVERSED", "0");
switch (GetRenderAPI())
{
@ -435,7 +444,7 @@ bool PostProcessing::ReShadeFXShader::CreateModule(s32 buffer_width, s32 buffer_
cg->write_result(*mod);
// FileSystem::WriteBinaryFile("D:\\out.txt", mod->code.data(), mod->code.size());
FileSystem::WriteBinaryFile("D:\\out.txt", mod->code.data(), mod->code.size());
return true;
}
@ -837,11 +846,16 @@ bool PostProcessing::ReShadeFXShader::GetSourceOption(const reshadefx::uniform_i
*si = (ui.type.base == reshadefx::type::t_float) ? SourceOptionType::RandomF : SourceOptionType::Random;
return true;
}
else if (source == "overlay_active" || source == "has_depth")
else if (source == "overlay_active")
{
*si = SourceOptionType::Zero;
return true;
}
else if (source == "has_depth")
{
*si = SourceOptionType::HasDepth;
return true;
}
else if (source == "bufferwidth")
{
*si = (ui.type.base == reshadefx::type::t_float) ? SourceOptionType::BufferWidthF : SourceOptionType::BufferWidth;
@ -1185,8 +1199,8 @@ bool PostProcessing::ReShadeFXShader::CreatePasses(GPUTexture::Format backbuffer
}
else if (ti.semantic == "DEPTH")
{
WARNING_LOG("Shader '{}' uses input depth as '{}' which is not supported.", m_name, si.texture_name);
sampler.texture_id = INPUT_DEPTH_TEXTURE;
m_wants_depth_buffer = true;
break;
}
else if (!ti.semantic.empty())
@ -1252,18 +1266,18 @@ const char* PostProcessing::ReShadeFXShader::GetTextureNameForID(TextureID id) c
return m_textures[static_cast<size_t>(id)].reshade_name.c_str();
}
GPUTexture* PostProcessing::ReShadeFXShader::GetTextureByID(TextureID id, GPUTexture* input,
GPUTexture* final_target) const
GPUTexture* PostProcessing::ReShadeFXShader::GetTextureByID(TextureID id, GPUTexture* input_color,
GPUTexture* input_depth, GPUTexture* final_target) const
{
if (id < 0)
{
if (id == INPUT_COLOR_TEXTURE)
{
return input;
return input_color;
}
else if (id == INPUT_DEPTH_TEXTURE)
{
return PostProcessing::GetDummyTexture();
return input_depth ? input_depth : GetDummyTexture();
}
else if (id == OUTPUT_COLOR_TEXTURE)
{
@ -1291,6 +1305,7 @@ bool PostProcessing::ReShadeFXShader::CompilePipeline(GPUTexture::Format format,
m_valid = false;
m_textures.clear();
m_passes.clear();
m_wants_depth_buffer = false;
std::string fxcode;
if (!PreprocessorReadFileCallback(m_filename, fxcode))
@ -1474,9 +1489,10 @@ bool PostProcessing::ReShadeFXShader::ResizeOutput(GPUTexture::Format format, u3
return true;
}
bool PostProcessing::ReShadeFXShader::Apply(GPUTexture* input, GPUTexture* final_target, s32 final_left, s32 final_top,
s32 final_width, s32 final_height, s32 orig_width, s32 orig_height,
s32 native_width, s32 native_height, u32 target_width, u32 target_height)
bool PostProcessing::ReShadeFXShader::Apply(GPUTexture* input_color, GPUTexture* input_depth, GPUTexture* final_target,
s32 final_left, s32 final_top, s32 final_width, s32 final_height,
s32 orig_width, s32 orig_height, s32 native_width, s32 native_height,
u32 target_width, u32 target_height)
{
GL_PUSH_FMT("PostProcessingShaderFX {}", m_name);
@ -1507,6 +1523,13 @@ bool PostProcessing::ReShadeFXShader::Apply(GPUTexture* input, GPUTexture* final
}
break;
case SourceOptionType::HasDepth:
{
const u32 value = BoolToUInt32(input_depth != nullptr);
std::memcpy(dst, &value, sizeof(value));
}
break;
case SourceOptionType::Timer:
{
const float value = static_cast<float>(PostProcessing::GetTimer().GetTimeMilliseconds());
@ -1750,7 +1773,7 @@ bool PostProcessing::ReShadeFXShader::Apply(GPUTexture* input, GPUTexture* final
// Sucks doing this twice, but we need to set the RT first (for DX11), and transition layouts (for VK).
for (const Sampler& sampler : pass.samplers)
{
GPUTexture* const tex = GetTextureByID(sampler.texture_id, input, final_target);
GPUTexture* const tex = GetTextureByID(sampler.texture_id, input_color, input_depth, final_target);
if (tex)
tex->MakeReadyForSampling();
}
@ -1771,7 +1794,7 @@ bool PostProcessing::ReShadeFXShader::Apply(GPUTexture* input, GPUTexture* final
{
GL_INS_FMT("Render Target {}: ID {} [{}]", i, pass.render_targets[i],
GetTextureNameForID(pass.render_targets[i]));
render_targets[i] = GetTextureByID(pass.render_targets[i], input, final_target);
render_targets[i] = GetTextureByID(pass.render_targets[i], input_color, input_depth, final_target);
DebugAssert(render_targets[i]);
}
@ -1795,8 +1818,8 @@ bool PostProcessing::ReShadeFXShader::Apply(GPUTexture* input, GPUTexture* final
GL_INS_FMT("Texture Sampler {}: ID {} [{}]", sampler.slot, sampler.texture_id,
GetTextureNameForID(sampler.texture_id));
g_gpu_device->SetTextureSampler(sampler.slot, GetTextureByID(sampler.texture_id, input, final_target),
sampler.sampler);
g_gpu_device->SetTextureSampler(
sampler.slot, GetTextureByID(sampler.texture_id, input_color, input_depth, final_target), sampler.sampler);
bound_textures[sampler.slot] = true;
}
@ -1811,6 +1834,10 @@ bool PostProcessing::ReShadeFXShader::Apply(GPUTexture* input, GPUTexture* final
g_gpu_device->Draw(pass.num_vertices, 0);
}
// Don't leave any textures bound.
for (u32 i = 0; i < GPUDevice::MAX_TEXTURE_SAMPLERS; i++)
g_gpu_device->SetTextureSampler(i, nullptr, nullptr);
GL_POP();
m_frame_timer.Reset();
return true;

View File

@ -24,15 +24,16 @@ public:
~ReShadeFXShader();
bool IsValid() const override;
bool WantsDepthBuffer() const override;
bool LoadFromFile(std::string name, std::string filename, bool only_config, Error* error);
bool LoadFromString(std::string name, std::string filename, std::string code, bool only_config, Error* error);
bool ResizeOutput(GPUTexture::Format format, u32 width, u32 height) override;
bool CompilePipeline(GPUTexture::Format format, u32 width, u32 height, ProgressCallback* progress) override;
bool Apply(GPUTexture* input, GPUTexture* final_target, s32 final_left, s32 final_top, s32 final_width,
s32 final_height, s32 orig_width, s32 orig_height, s32 native_width, s32 native_height, u32 target_width,
u32 target_height) override;
bool Apply(GPUTexture* input_color, GPUTexture* input_depth, GPUTexture* final_target, s32 final_left, s32 final_top,
s32 final_width, s32 final_height, s32 orig_width, s32 orig_height, s32 native_width, s32 native_height,
u32 target_width, u32 target_height) override;
private:
using TextureID = s32;
@ -45,6 +46,7 @@ private:
{
None,
Zero,
HasDepth,
Timer,
FrameTime,
FrameCount,
@ -98,7 +100,8 @@ private:
bool CreatePasses(GPUTexture::Format backbuffer_format, reshadefx::module& mod, Error* error);
const char* GetTextureNameForID(TextureID id) const;
GPUTexture* GetTextureByID(TextureID id, GPUTexture* input, GPUTexture* final_target) const;
GPUTexture* GetTextureByID(TextureID id, GPUTexture* input_color, GPUTexture* input_depth,
GPUTexture* final_target) const;
std::string m_filename;
@ -135,6 +138,7 @@ private:
std::vector<SourceOption> m_source_options;
u32 m_uniforms_size = 0;
bool m_valid = false;
bool m_wants_depth_buffer = false;
Common::Timer m_frame_timer;
u32 m_frame_count = 0;

View File

@ -62,6 +62,11 @@ bool PostProcessing::GLSLShader::IsValid() const
return !m_name.empty() && !m_code.empty();
}
bool PostProcessing::GLSLShader::WantsDepthBuffer() const
{
return false;
}
u32 PostProcessing::GLSLShader::GetUniformsSize() const
{
// lazy packing. todo improve.
@ -162,9 +167,10 @@ bool PostProcessing::GLSLShader::CompilePipeline(GPUTexture::Format format, u32
return true;
}
bool PostProcessing::GLSLShader::Apply(GPUTexture* input, GPUTexture* final_target, s32 final_left, s32 final_top,
s32 final_width, s32 final_height, s32 orig_width, s32 orig_height,
s32 native_width, s32 native_height, u32 target_width, u32 target_height)
bool PostProcessing::GLSLShader::Apply(GPUTexture* input_color, GPUTexture* input_depth, GPUTexture* final_target,
s32 final_left, s32 final_top, s32 final_width, s32 final_height, s32 orig_width,
s32 orig_height, s32 native_width, s32 native_height, u32 target_width,
u32 target_height)
{
GL_SCOPE_FMT("GLSL Shader {}", m_name);
@ -181,7 +187,7 @@ bool PostProcessing::GLSLShader::Apply(GPUTexture* input, GPUTexture* final_targ
}
g_gpu_device->SetPipeline(m_pipeline.get());
g_gpu_device->SetTextureSampler(0, input, m_sampler.get());
g_gpu_device->SetTextureSampler(0, input_color, m_sampler.get());
g_gpu_device->SetViewportAndScissor(final_left, final_top, final_width, final_height);
const u32 uniforms_size = GetUniformsSize();

View File

@ -17,15 +17,16 @@ public:
ALWAYS_INLINE const std::string& GetCode() const { return m_code; }
bool IsValid() const override;
bool WantsDepthBuffer() const override;
bool LoadFromFile(std::string name, const char* filename, Error* error);
bool LoadFromString(std::string name, std::string code, Error* error);
bool ResizeOutput(GPUTexture::Format format, u32 width, u32 height) override;
bool CompilePipeline(GPUTexture::Format format, u32 width, u32 height, ProgressCallback* progress) override;
bool Apply(GPUTexture* input, GPUTexture* final_target, s32 final_left, s32 final_top, s32 final_width,
s32 final_height, s32 orig_width, s32 orig_height, s32 native_width, s32 native_height, u32 target_width,
u32 target_height) override;
bool Apply(GPUTexture* input_color, GPUTexture* input_depth, GPUTexture* final_target, s32 final_left, s32 final_top,
s32 final_width, s32 final_height, s32 orig_width, s32 orig_height, s32 native_width, s32 native_height,
u32 target_width, u32 target_height) override;
private:
struct CommonUniforms