diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 05a4fa5d71..a2039a3b25 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1068,7 +1068,6 @@ set (PCH_SOURCES rendering/gl/renderer/gl_scene.cpp rendering/gl/shaders/gl_shader.cpp rendering/gl/shaders/gl_shaderprogram.cpp - rendering/gl/shaders/gl_postprocessshader.cpp rendering/gl_load/gl_interface.cpp rendering/gl/system/gl_framebuffer.cpp rendering/gl/system/gl_debug.cpp diff --git a/src/rendering/gl/renderer/gl_postprocess.cpp b/src/rendering/gl/renderer/gl_postprocess.cpp index 8b1482565f..c233b80c7a 100644 --- a/src/rendering/gl/renderer/gl_postprocess.cpp +++ b/src/rendering/gl/renderer/gl_postprocess.cpp @@ -43,7 +43,6 @@ #include "hwrenderer/postprocessing/hw_postprocess_cvars.h" #include "hwrenderer/utility/hw_vrmodes.h" #include "hwrenderer/data/flatvertices.h" -#include "gl/shaders/gl_postprocessshaderinstance.h" #include "gl/textures/gl_hwtexture.h" #include "r_videoscale.h" @@ -70,7 +69,7 @@ void FGLRenderer::PostProcessScene(int fixedcm, const std::function &aft GLPPRenderState renderstate(mBuffers); hw_postprocess.exposure.Render(&renderstate, sceneWidth, sceneHeight); - mCustomPostProcessShaders->Run("beforebloom"); + hw_postprocess.customShaders.Run(&renderstate, "beforebloom"); hw_postprocess.bloom.RenderBloom(&renderstate, sceneWidth, sceneHeight, fixedcm); mBuffers->BindCurrentFB(); @@ -80,7 +79,7 @@ void FGLRenderer::PostProcessScene(int fixedcm, const std::function &aft hw_postprocess.colormap.Render(&renderstate, fixedcm); hw_postprocess.lens.Render(&renderstate); hw_postprocess.fxaa.Render(&renderstate); - mCustomPostProcessShaders->Run("scene"); + hw_postprocess.customShaders.Run(&renderstate, "scene"); } //----------------------------------------------------------------------------- @@ -164,7 +163,8 @@ void FGLRenderer::CopyToBackbuffer(const IntRect *bounds, bool applyGamma) screen->Draw2D(); // draw all pending 2D stuff before copying the buffer screen->Clear2D(); - mCustomPostProcessShaders->Run("screen"); + GLPPRenderState renderstate(mBuffers); + hw_postprocess.customShaders.Run(&renderstate, "screen"); FGLDebug::PushGroup("CopyToBackbuffer"); FGLPostProcessState savedState; diff --git a/src/rendering/gl/renderer/gl_renderer.cpp b/src/rendering/gl/renderer/gl_renderer.cpp index 0de84e6dad..cab613aa98 100644 --- a/src/rendering/gl/renderer/gl_renderer.cpp +++ b/src/rendering/gl/renderer/gl_renderer.cpp @@ -52,7 +52,6 @@ #include "hwrenderer/data/flatvertices.h" #include "hwrenderer/scene/hw_skydome.h" #include "hwrenderer/scene/hw_fakeflat.h" -#include "gl/shaders/gl_postprocessshaderinstance.h" #include "gl/textures/gl_samplers.h" #include "hwrenderer/dynlights/hw_lightbuffer.h" #include "hwrenderer/data/hw_viewpointbuffer.h" @@ -97,7 +96,6 @@ void FGLRenderer::Initialize(int width, int height) mPresent3dColumnShader = new FPresent3DColumnShader(); mPresent3dRowShader = new FPresent3DRowShader(); mShadowMapShader = new FShadowMapShader(); - mCustomPostProcessShaders = new FCustomPostProcessShaders(); // needed for the core profile, because someone decided it was a good idea to remove the default VAO. glGenQueries(1, &PortalQueryObject); @@ -135,7 +133,6 @@ FGLRenderer::~FGLRenderer() if (mPresent3dColumnShader) delete mPresent3dColumnShader; if (mPresent3dRowShader) delete mPresent3dRowShader; if (mShadowMapShader) delete mShadowMapShader; - delete mCustomPostProcessShaders; } //=========================================================================== diff --git a/src/rendering/gl/renderer/gl_renderer.h b/src/rendering/gl/renderer/gl_renderer.h index 0514a48663..3339eda275 100644 --- a/src/rendering/gl/renderer/gl_renderer.h +++ b/src/rendering/gl/renderer/gl_renderer.h @@ -33,7 +33,6 @@ struct FRenderViewpoint; namespace OpenGLRenderer { class FSamplerManager; - class FCustomPostProcessShaders; class OpenGLFrameBuffer; class FPresentShaderBase; class FPresentShader; @@ -66,7 +65,6 @@ public: FPresent3DColumnShader *mPresent3dColumnShader = nullptr; FPresent3DRowShader *mPresent3dRowShader = nullptr; FShadowMapShader *mShadowMapShader = nullptr; - FCustomPostProcessShaders *mCustomPostProcessShaders = nullptr; //FRotator mAngles; diff --git a/src/rendering/gl/shaders/gl_postprocessshader.cpp b/src/rendering/gl/shaders/gl_postprocessshader.cpp deleted file mode 100644 index d197e11cfa..0000000000 --- a/src/rendering/gl/shaders/gl_postprocessshader.cpp +++ /dev/null @@ -1,250 +0,0 @@ -// -//--------------------------------------------------------------------------- -// -// Copyright(C) 2017 Magnus Norddahl -// All rights reserved. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with this program. If not, see http://www.gnu.org/licenses/ -// -//-------------------------------------------------------------------------- -// - -#include "gl_load/gl_system.h" -#include "v_video.h" -#include "w_wad.h" -#include "gl_load/gl_interface.h" -#include "gl/system/gl_debug.h" -#include "gl/renderer/gl_renderer.h" -#include "gl/renderer/gl_postprocessstate.h" -#include "gl/renderer/gl_renderbuffers.h" -#include "hwrenderer/postprocessing/hw_postprocessshader.h" -#include "gl/shaders/gl_postprocessshaderinstance.h" -#include "textures/bitmap.h" - -CVAR(Bool, gl_custompost, true, 0) - -namespace OpenGLRenderer -{ - - -FCustomPostProcessShaders::FCustomPostProcessShaders() -{ - for (unsigned int i = 0; i < PostProcessShaders.Size(); i++) - { - mShaders.push_back(std::unique_ptr(new PostProcessShaderInstance(&PostProcessShaders[i]))); - } -} - -FCustomPostProcessShaders::~FCustomPostProcessShaders() -{ -} - -void FCustomPostProcessShaders::Run(FString target) -{ - if (!gl_custompost) - return; - - for (auto &shader : mShaders) - { - if (shader->Desc->Target == target) - { - shader->Run(); - } - } -} - -///////////////////////////////////////////////////////////////////////////// - -PostProcessShaderInstance::~PostProcessShaderInstance() -{ - for (const auto &it : mTextureHandles) - glDeleteTextures(1, (GLuint*)&it.second); -} - -void PostProcessShaderInstance::Run() -{ - if (!IsShaderSupported()) - return; - - CompileShader(); - - if (!Desc->Enabled) - return; - - FGLDebug::PushGroup(Desc->ShaderLumpName.GetChars()); - - FGLPostProcessState savedState; - savedState.SaveTextureBindings(1 + Desc->Textures.CountUsed()); - - GLRenderer->mBuffers->BindNextFB(); - GLRenderer->mBuffers->BindCurrentTexture(0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - mProgram.Bind(); - - UpdateUniforms(); - BindTextures(); - - GLRenderer->RenderScreenQuad(); - - glActiveTexture(GL_TEXTURE0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - GLRenderer->mBuffers->NextTexture(); - - FGLDebug::PopGroup(); -} - -bool PostProcessShaderInstance::IsShaderSupported() -{ - int activeShaderVersion = (int)round(gl.glslversion * 10) * 10; - return activeShaderVersion >= Desc->ShaderVersion; -} - -void PostProcessShaderInstance::CompileShader() -{ - if (mProgram.Handle()) - return; - - // Get the custom shader - const char *lumpName = Desc->ShaderLumpName.GetChars(); - int lump = Wads.CheckNumForFullName(lumpName); - if (lump == -1) I_FatalError("Unable to load '%s'", lumpName); - FString code = Wads.ReadLump(lump).GetString().GetChars(); - - // Build an uniform block to use be used as input - // (this is technically not an uniform block, but it could be changed into that for Vulkan GLSL support) - FString uniformBlock; - TMap::Iterator it(Desc->Uniforms); - TMap::Pair *pair; - while (it.NextPair(pair)) - { - FString type; - FString name = pair->Key; - - switch (pair->Value.Type) - { - case PostProcessUniformType::Float: type = "float"; break; - case PostProcessUniformType::Int: type = "int"; break; - case PostProcessUniformType::Vec2: type = "vec2"; break; - case PostProcessUniformType::Vec3: type = "vec3"; break; - default: break; - } - - if (!type.IsEmpty()) - uniformBlock.AppendFormat("uniform %s %s;\n", type.GetChars(), name.GetChars()); - } - - // Build the input textures - FString uniformTextures; - uniformTextures += "uniform sampler2D InputTexture;\n"; - - TMap::Iterator itTextures(Desc->Textures); - TMap::Pair *pairTextures; - while (itTextures.NextPair(pairTextures)) - { - uniformTextures.AppendFormat("uniform sampler2D %s;\n", pairTextures->Key.GetChars()); - } - - // Setup pipeline - FString pipelineInOut; - pipelineInOut += "in vec2 TexCoord;\n"; - pipelineInOut += "out vec4 FragColor;\n"; - - FString prolog; - prolog += uniformBlock; - prolog += uniformTextures; - prolog += pipelineInOut; - - mProgram.Compile(FShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", Desc->ShaderVersion); - mProgram.Compile(FShaderProgram::Fragment, lumpName, code, prolog.GetChars(), Desc->ShaderVersion); - mProgram.Link(Desc->ShaderLumpName.GetChars()); - mInputTexture.Init(mProgram.Handle(), "InputTexture"); -} - -void PostProcessShaderInstance::UpdateUniforms() -{ - TMap::Iterator it(Desc->Uniforms); - TMap::Pair *pair; - while (it.NextPair(pair)) - { - int location = glGetUniformLocation(mProgram.Handle(), pair->Key.GetChars()); - if (location != -1) - { - switch (pair->Value.Type) - { - case PostProcessUniformType::Float: - glUniform1f(location, (float)pair->Value.Values[0]); - break; - case PostProcessUniformType::Int: - glUniform1i(location, (int)pair->Value.Values[0]); - break; - case PostProcessUniformType::Vec2: - glUniform2f(location, (float)pair->Value.Values[0], (float)pair->Value.Values[1]); - break; - case PostProcessUniformType::Vec3: - glUniform3f(location, (float)pair->Value.Values[0], (float)pair->Value.Values[1], (float)pair->Value.Values[2]); - break; - default: - break; - } - } - } -} - -void PostProcessShaderInstance::BindTextures() -{ - int textureUnit = 1; - TMap::Iterator it(Desc->Textures); - TMap::Pair *pair; - while (it.NextPair(pair)) - { - int location = glGetUniformLocation(mProgram.Handle(), pair->Key.GetChars()); - if (location == -1) - continue; - - FString name = pair->Value; - FTexture *tex = TexMan.GetTexture(TexMan.CheckForTexture(name, ETextureType::Any), true); - if (tex && tex->isValid()) - { - glUniform1i(location, textureUnit); - - glActiveTexture(GL_TEXTURE0 + textureUnit); - auto it = mTextureHandles.find(tex); - if (it == mTextureHandles.end()) - { - // Why does this completely circumvent the normal way of handling textures? - // This absolutely needs fixing because it will also circumvent any potential caching system that may get implemented. - auto buffer = tex->CreateTexBuffer(0); - - GLuint handle = 0; - glGenTextures(1, &handle); - glBindTexture(GL_TEXTURE_2D, handle); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, buffer.mWidth, buffer.mHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, buffer.mBuffer); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - mTextureHandles[tex] = handle; - } - else - { - glBindTexture(GL_TEXTURE_2D, it->second); - } - - textureUnit++; - } - } -} - -} diff --git a/src/rendering/gl/shaders/gl_postprocessshaderinstance.h b/src/rendering/gl/shaders/gl_postprocessshaderinstance.h deleted file mode 100644 index 0861467382..0000000000 --- a/src/rendering/gl/shaders/gl_postprocessshaderinstance.h +++ /dev/null @@ -1,49 +0,0 @@ -#pragma once - -#include "gl_shaderprogram.h" -#include - -struct PostProcessShader; - -namespace OpenGLRenderer -{ - - -class PostProcessShaderInstance -{ -public: - PostProcessShaderInstance(PostProcessShader *desc) : Desc(desc) { } - ~PostProcessShaderInstance(); - - void Run(); - - PostProcessShader *Desc; - -private: - bool IsShaderSupported(); - void CompileShader(); - void UpdateUniforms(); - void BindTextures(); - - FShaderProgram mProgram; - FUniform1i mInputTexture; - std::map mTextureHandles; -}; - -class FCustomPostProcessShaders -{ -public: - FCustomPostProcessShaders(); - ~FCustomPostProcessShaders(); - - void Run(FString target); - -private: - std::vector> mShaders; - - FCustomPostProcessShaders(const FCustomPostProcessShaders &) = delete; - FCustomPostProcessShaders &operator=(const FCustomPostProcessShaders &) = delete; -}; - - -} \ No newline at end of file diff --git a/src/rendering/gl/shaders/gl_shaderprogram.cpp b/src/rendering/gl/shaders/gl_shaderprogram.cpp index d7c49f3213..5cc4863321 100644 --- a/src/rendering/gl/shaders/gl_shaderprogram.cpp +++ b/src/rendering/gl/shaders/gl_shaderprogram.cpp @@ -91,7 +91,7 @@ void FShaderProgram::CreateShader(ShaderType type) void FShaderProgram::Compile(ShaderType type, const char *lumpName, const char *defines, int maxGlslVersion) { - int lump = Wads.CheckNumForFullName(lumpName, 0); + int lump = Wads.CheckNumForFullName(lumpName); if (lump == -1) I_FatalError("Unable to load '%s'", lumpName); FString code = Wads.ReadLump(lump).GetString().GetChars(); Compile(type, lumpName, code, defines, maxGlslVersion); diff --git a/src/rendering/hwrenderer/postprocessing/hw_postprocess.cpp b/src/rendering/hwrenderer/postprocessing/hw_postprocess.cpp index 2fd47d6c4d..99e9b509a7 100644 --- a/src/rendering/hwrenderer/postprocessing/hw_postprocess.cpp +++ b/src/rendering/hwrenderer/postprocessing/hw_postprocess.cpp @@ -3,6 +3,7 @@ #include "hw_postprocess.h" #include "hwrenderer/utility/hw_cvars.h" #include "hwrenderer/postprocessing/hw_postprocess_cvars.h" +#include "hwrenderer/postprocessing/hw_postprocessshader.h" #include Postprocess hw_postprocess; @@ -443,7 +444,10 @@ void PPCameraExposure::Render(PPRenderState *renderstate, int sceneWidth, int sc void PPCameraExposure::UpdateTextures(int width, int height) { - if (ExposureLevels.size() > 0 && ExposureLevels[0].Viewport.width == width && ExposureLevels[0].Viewport.height == height) + int firstwidth = MAX(width / 2, 1); + int firstheight = MAX(height / 2, 1); + + if (ExposureLevels.size() > 0 && ExposureLevels[0].Viewport.width == firstwidth && ExposureLevels[0].Viewport.height == firstheight) { return; } @@ -802,3 +806,203 @@ void PPShadowMap::Update(PPRenderState *renderstate) renderstate->SetNoBlend(); renderstate->Draw(); } + +///////////////////////////////////////////////////////////////////////////// + +CVAR(Bool, gl_custompost, true, 0) + +void PPCustomShaders::Run(PPRenderState *renderstate, FString target) +{ + if (!gl_custompost) + return; + + CreateShaders(); + + for (auto &shader : mShaders) + { + if (shader->Desc->Target == target && shader->Desc->Enabled) + { + shader->Run(renderstate); + } + } +} + +void PPCustomShaders::CreateShaders() +{ + if (mShaders.size() == PostProcessShaders.Size()) + return; + + mShaders.clear(); + + for (unsigned int i = 0; i < PostProcessShaders.Size(); i++) + { + mShaders.push_back(std::make_unique(&PostProcessShaders[i])); + } +} + +///////////////////////////////////////////////////////////////////////////// + +PPCustomShaderInstance::PPCustomShaderInstance(PostProcessShader *desc) : Desc(desc) +{ + // Build an uniform block to be used as input + TMap::Iterator it(Desc->Uniforms); + TMap::Pair *pair; + size_t offset = 0; + while (it.NextPair(pair)) + { + FString type; + FString name = pair->Key; + + switch (pair->Value.Type) + { + case PostProcessUniformType::Float: AddUniformField(offset, name, UniformType::Float, sizeof(float)); break; + case PostProcessUniformType::Int: AddUniformField(offset, name, UniformType::Int, sizeof(int)); break; + case PostProcessUniformType::Vec2: AddUniformField(offset, name, UniformType::Vec2, sizeof(float) * 2); break; + case PostProcessUniformType::Vec3: AddUniformField(offset, name, UniformType::Vec3, sizeof(float) * 3); break; + default: break; + } + } + UniformStructSize = ((int)offset + 15) / 16 * 16; + + // Build the input textures + FString uniformTextures; + uniformTextures += "layout(binding=0) uniform sampler2D InputTexture;\n"; + + TMap::Iterator itTextures(Desc->Textures); + TMap::Pair *pairTextures; + int binding = 1; + while (itTextures.NextPair(pairTextures)) + { + uniformTextures.AppendFormat("layout(binding=%d) uniform sampler2D %s;\n", binding++, pairTextures->Key.GetChars()); + } + + // Setup pipeline + FString pipelineInOut; + pipelineInOut += "layout(location=0) in vec2 TexCoord;\n"; + pipelineInOut += "layout(location=0) out vec4 FragColor;\n"; + + FString prolog; + prolog += uniformTextures; + prolog += pipelineInOut; + + Shader = PPShader(Desc->ShaderLumpName, prolog, Fields); +} + +void PPCustomShaderInstance::Run(PPRenderState *renderstate) +{ + renderstate->Clear(); + renderstate->Shader = &Shader; + renderstate->Viewport = screen->mScreenViewport; + renderstate->SetNoBlend(); + renderstate->SetOutputNext(); + //renderstate->SetDebugName(Desc->ShaderLumpName.GetChars()); + + SetTextures(renderstate); + SetUniforms(renderstate); + + renderstate->Draw(); +} + +void PPCustomShaderInstance::SetTextures(PPRenderState *renderstate) +{ + renderstate->SetInputCurrent(0, PPFilterMode::Linear); + + int textureIndex = 1; + TMap::Iterator it(Desc->Textures); + TMap::Pair *pair; + while (it.NextPair(pair)) + { + FString name = pair->Value; + FTexture *tex = TexMan.GetTexture(TexMan.CheckForTexture(name, ETextureType::Any), true); + if (tex && tex->isValid()) + { + // Why does this completely circumvent the normal way of handling textures? + // This absolutely needs fixing because it will also circumvent any potential caching system that may get implemented. + // + // To do: fix the above problem by adding PPRenderState::SetInput(FTexture *tex) + + auto &pptex = Textures[tex]; + if (!pptex) + { + auto buffer = tex->CreateTexBuffer(0); + + std::shared_ptr data(new uint32_t[buffer.mWidth * buffer.mHeight], [](void *p) { delete[](uint32_t*)p; }); + + int count = buffer.mWidth * buffer.mHeight; + uint8_t *pixels = (uint8_t *)data.get(); + for (int i = 0; i < count; i++) + { + int pos = i << 2; + pixels[pos] = buffer.mBuffer[pos + 2]; + pixels[pos + 1] = buffer.mBuffer[pos + 1]; + pixels[pos + 2] = buffer.mBuffer[pos]; + pixels[pos + 3] = buffer.mBuffer[pos + 3]; + } + + pptex = std::make_unique(buffer.mWidth, buffer.mHeight, PixelFormat::Rgba8, data); + } + + renderstate->SetInputTexture(textureIndex, pptex.get(), PPFilterMode::Linear); + textureIndex++; + } + } +} + +void PPCustomShaderInstance::SetUniforms(PPRenderState *renderstate) +{ + TArray uniforms; + uniforms.Resize(UniformStructSize); + + TMap::Iterator it(Desc->Uniforms); + TMap::Pair *pair; + while (it.NextPair(pair)) + { + auto it2 = FieldOffset.find(pair->Key); + if (it2 != FieldOffset.end()) + { + uint8_t *dst = &uniforms[it2->second]; + float fValues[4]; + int iValues[4]; + switch (pair->Value.Type) + { + case PostProcessUniformType::Float: + fValues[0] = (float)pair->Value.Values[0]; + memcpy(dst, fValues, sizeof(float)); + break; + case PostProcessUniformType::Int: + iValues[0] = (int)pair->Value.Values[0]; + memcpy(dst, iValues, sizeof(int)); + break; + case PostProcessUniformType::Vec2: + fValues[0] = (float)pair->Value.Values[0]; + fValues[1] = (float)pair->Value.Values[1]; + memcpy(dst, fValues, sizeof(float) * 2); + break; + case PostProcessUniformType::Vec3: + fValues[0] = (float)pair->Value.Values[0]; + fValues[1] = (float)pair->Value.Values[1]; + fValues[2] = (float)pair->Value.Values[2]; + memcpy(dst, fValues, sizeof(float) * 3); + break; + default: + break; + } + } + } + + renderstate->Uniforms.Data = uniforms; +} + +void PPCustomShaderInstance::AddUniformField(size_t &offset, const FString &name, UniformType type, size_t fieldsize) +{ + size_t alignment = fieldsize; + offset = (offset + alignment - 1) / alignment * alignment; + + FieldOffset[name] = offset; + + auto name2 = std::make_unique(name); + FieldNames.push_back(std::move(name2)); + Fields.push_back({ name2->GetChars(), type, offset }); + + offset += fieldsize; +} diff --git a/src/rendering/hwrenderer/postprocessing/hw_postprocess.h b/src/rendering/hwrenderer/postprocessing/hw_postprocess.h index 9b1df90afa..aba625a7c0 100644 --- a/src/rendering/hwrenderer/postprocessing/hw_postprocess.h +++ b/src/rendering/hwrenderer/postprocessing/hw_postprocess.h @@ -2,6 +2,9 @@ #include "hwrenderer/data/shaderuniforms.h" #include +#include + +struct PostProcessShader; typedef FRenderStyle PPBlendMode; typedef IntRect PPViewport; @@ -292,7 +295,7 @@ public: class PPShader : public PPResource { public: - PPShader() { } + PPShader() = default; PPShader(const FString &fragment, const FString &defines, const std::vector &uniforms, int version = 330) : FragmentShader(fragment), Defines(defines), Uniforms(uniforms), Version(version) { } void ResetBackend() override { Backend.reset(); } @@ -777,6 +780,40 @@ private: PPShader ShadowMap = { "shaders/glsl/shadowmap.fp", "", ShadowMapUniforms::Desc() }; }; +class PPCustomShaderInstance +{ +public: + PPCustomShaderInstance(PostProcessShader *desc); + + void Run(PPRenderState *renderstate); + + PostProcessShader *Desc = nullptr; + +private: + void CreateShaders(); + void AddUniformField(size_t &offset, const FString &name, UniformType type, size_t fieldsize); + void SetTextures(PPRenderState *renderstate); + void SetUniforms(PPRenderState *renderstate); + + PPShader Shader; + int UniformStructSize = 0; + std::vector Fields; + std::vector> FieldNames; + std::map> Textures; + std::map FieldOffset; +}; + +class PPCustomShaders +{ +public: + void Run(PPRenderState *renderstate, FString target); + +private: + void CreateShaders(); + + std::vector> mShaders; +}; + ///////////////////////////////////////////////////////////////////////////// class Postprocess @@ -791,6 +828,7 @@ public: PPAmbientOcclusion ssao; PPPresent present; PPShadowMap shadowmap; + PPCustomShaders customShaders; }; extern Postprocess hw_postprocess; diff --git a/src/rendering/vulkan/renderer/vk_postprocess.cpp b/src/rendering/vulkan/renderer/vk_postprocess.cpp index 907ffcbb4c..fbdd1cb103 100644 --- a/src/rendering/vulkan/renderer/vk_postprocess.cpp +++ b/src/rendering/vulkan/renderer/vk_postprocess.cpp @@ -46,7 +46,7 @@ void VkPostprocess::PostProcessScene(int fixedcm, const std::function &a VkPPRenderState renderstate; hw_postprocess.exposure.Render(&renderstate, sceneWidth, sceneHeight); - //mCustomPostProcessShaders->Run("beforebloom"); + hw_postprocess.customShaders.Run(&renderstate, "beforebloom"); hw_postprocess.bloom.RenderBloom(&renderstate, sceneWidth, sceneHeight, fixedcm); SetActiveRenderTarget(); @@ -56,7 +56,7 @@ void VkPostprocess::PostProcessScene(int fixedcm, const std::function &a hw_postprocess.colormap.Render(&renderstate, fixedcm); hw_postprocess.lens.Render(&renderstate); hw_postprocess.fxaa.Render(&renderstate); - //mCustomPostProcessShaders->Run("scene"); + hw_postprocess.customShaders.Run(&renderstate, "scene"); } void VkPostprocess::BlitSceneToPostprocess() @@ -175,6 +175,9 @@ void VkPostprocess::DrawPresentTexture(const IntRect &box, bool applyGamma, bool { auto fb = GetVulkanFrameBuffer(); + VkPPRenderState renderstate; + hw_postprocess.customShaders.Run(&renderstate, "screen"); + PresentUniforms uniforms; if (!applyGamma /*|| framebuffer->IsHWGammaActive()*/) { @@ -200,7 +203,7 @@ void VkPostprocess::DrawPresentTexture(const IntRect &box, bool applyGamma, bool uniforms.InvGamma *= 2.2f; } - VkPPRenderState renderstate; + renderstate.Clear(); renderstate.Shader = &hw_postprocess.present.Present; renderstate.Uniforms.Set(uniforms); renderstate.Viewport = box; @@ -266,8 +269,6 @@ void VkPostprocess::UpdateShadowMap() void VkPostprocess::BeginFrame() { - mFrameDescriptorSets.clear(); - if (!mDescriptorPool) { DescriptorPoolBuilder builder; @@ -533,8 +534,9 @@ VulkanDescriptorSet *VkPPRenderState::GetInput(VkPPRenderPassSetup *passSetup, c write.updateSets(fb->device); imageTransition.execute(fb->GetDrawCommands()); - pp->mFrameDescriptorSets.push_back(std::move(descriptors)); - return pp->mFrameDescriptorSets.back().get(); + VulkanDescriptorSet *set = descriptors.get(); + fb->FrameDeleteList.Descriptors.push_back(std::move(descriptors)); + return set; } VulkanFramebuffer *VkPPRenderState::GetOutput(VkPPRenderPassSetup *passSetup, const PPOutput &output, int &framebufferWidth, int &framebufferHeight) diff --git a/src/rendering/vulkan/renderer/vk_postprocess.h b/src/rendering/vulkan/renderer/vk_postprocess.h index 50a5549f3d..ace4afdfe9 100644 --- a/src/rendering/vulkan/renderer/vk_postprocess.h +++ b/src/rendering/vulkan/renderer/vk_postprocess.h @@ -78,7 +78,6 @@ private: std::array, 16> mSamplers; std::map> mRenderPassSetup; std::unique_ptr mDescriptorPool; - std::vector> mFrameDescriptorSets; int mCurrentPipelineImage = 0; friend class VkPPRenderState;