postprocessing.h (4979B)
1 // SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com> 2 // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) 3 4 #pragma once 5 6 #include "gpu_device.h" 7 8 #include <array> 9 #include <memory> 10 #include <mutex> 11 #include <string_view> 12 #include <vector> 13 14 namespace Common { 15 class Timer; 16 } 17 18 class GPUSampler; 19 class GPUTexture; 20 21 class Error; 22 class SettingsInterface; 23 class ProgressCallback; 24 25 namespace PostProcessing { 26 class Shader; 27 28 struct ShaderOption 29 { 30 enum : u32 31 { 32 MAX_VECTOR_COMPONENTS = 4 33 }; 34 35 enum class Type 36 { 37 Invalid, 38 Bool, 39 Int, 40 Float 41 }; 42 43 union Value 44 { 45 s32 int_value; 46 float float_value; 47 }; 48 static_assert(sizeof(Value) == sizeof(u32)); 49 50 using ValueVector = std::array<Value, MAX_VECTOR_COMPONENTS>; 51 static_assert(sizeof(ValueVector) == sizeof(u32) * MAX_VECTOR_COMPONENTS); 52 53 std::string name; 54 std::string ui_name; 55 std::string dependent_option; 56 std::string category; 57 std::string tooltip; 58 Type type; 59 u32 vector_size; 60 u32 buffer_size; 61 u32 buffer_offset; 62 ValueVector default_value; 63 ValueVector min_value; 64 ValueVector max_value; 65 ValueVector step_value; 66 ValueVector value; 67 std::vector<std::string> choice_options; 68 69 static u32 ParseIntVector(std::string_view line, ValueVector* values); 70 static u32 ParseFloatVector(std::string_view line, ValueVector* values); 71 72 static constexpr ValueVector MakeIntVector(s32 x, s32 y = 0, s32 z = 0, s32 w = 0) 73 { 74 ValueVector ret = {}; 75 ret[0].int_value = x; 76 ret[1].int_value = y; 77 ret[2].int_value = z; 78 ret[3].int_value = w; 79 return ret; 80 } 81 82 static constexpr ValueVector MakeFloatVector(float x, float y = 0, float z = 0, float w = 0) 83 { 84 ValueVector ret = {}; 85 ret[0].float_value = x; 86 ret[1].float_value = y; 87 ret[2].float_value = z; 88 ret[3].float_value = w; 89 return ret; 90 } 91 }; 92 93 namespace Config { 94 static constexpr const char* DISPLAY_CHAIN_SECTION = "PostProcessing"; 95 static constexpr const char* INTERNAL_CHAIN_SECTION = "InternalPostProcessing"; 96 97 u32 GetStageCount(const SettingsInterface& si, const char* section); 98 std::string GetStageShaderName(const SettingsInterface& si, const char* section, u32 index); 99 std::vector<ShaderOption> GetStageOptions(const SettingsInterface& si, const char* section, u32 index); 100 std::vector<ShaderOption> GetShaderOptions(const std::string& shader_name, Error* error); 101 102 bool AddStage(SettingsInterface& si, const char* section, const std::string& shader_name, Error* error); 103 void RemoveStage(SettingsInterface& si, const char* section, u32 index); 104 void MoveStageUp(SettingsInterface& si, const char* section, u32 index); 105 void MoveStageDown(SettingsInterface& si, const char* section, u32 index); 106 void SetStageOption(SettingsInterface& si, const char* section, u32 index, const ShaderOption& option); 107 void UnsetStageOption(SettingsInterface& si, const char* section, u32 index, const ShaderOption& option); 108 void ClearStages(SettingsInterface& si, const char* section); 109 } // namespace Config 110 111 class Chain 112 { 113 public: 114 Chain(const char* section); 115 ~Chain(); 116 117 ALWAYS_INLINE bool HasStages() const { return m_stages.empty(); } 118 ALWAYS_INLINE bool NeedsDepthBuffer() const { return m_needs_depth_buffer; } 119 ALWAYS_INLINE GPUTexture* GetInputTexture() const { return m_input_texture.get(); } 120 ALWAYS_INLINE GPUTexture* GetOutputTexture() const { return m_output_texture.get(); } 121 122 bool IsActive() const; 123 bool IsInternalChain() const; 124 125 void UpdateSettings(std::unique_lock<std::mutex>& settings_lock); 126 127 void LoadStages(); 128 void ClearStages(); 129 void DestroyTextures(); 130 131 /// Temporarily toggles post-processing on/off. 132 void Toggle(); 133 134 bool CheckTargets(GPUTexture::Format target_format, u32 target_width, u32 target_height, 135 ProgressCallback* progress = nullptr); 136 137 bool Apply(GPUTexture* input_color, GPUTexture* input_depth, GPUTexture* final_target, const GSVector4i final_rect, 138 s32 orig_width, s32 orig_height, s32 native_width, s32 native_height); 139 140 private: 141 void ClearStagesWithError(const Error& error); 142 143 const char* m_section; 144 145 GPUTexture::Format m_target_format = GPUTexture::Format::Unknown; 146 u32 m_target_width = 0; 147 u32 m_target_height = 0; 148 bool m_enabled = false; 149 bool m_wants_depth_buffer = false; 150 bool m_needs_depth_buffer = false; 151 152 std::vector<std::unique_ptr<PostProcessing::Shader>> m_stages; 153 std::unique_ptr<GPUTexture> m_input_texture; 154 std::unique_ptr<GPUTexture> m_output_texture; 155 }; 156 157 // [display_name, filename] 158 std::vector<std::pair<std::string, std::string>> GetAvailableShaderNames(); 159 160 void Initialize(); 161 162 /// Reloads configuration. 163 void UpdateSettings(); 164 165 /// Reloads post processing shaders with the current configuration. 166 bool ReloadShaders(); 167 168 void Shutdown(); 169 170 GPUSampler* GetSampler(const GPUSampler::Config& config); 171 GPUTexture* GetDummyTexture(); 172 173 const Common::Timer& GetTimer(); 174 175 extern Chain DisplayChain; 176 extern Chain InternalChain; 177 178 }; // namespace PostProcessing