mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-13 07:57:58 +00:00
Merge branch 'vulkan2' of https://github.com/coelckers/gzdoom into vulkan2
This commit is contained in:
commit
c6a308c73d
11 changed files with 258 additions and 320 deletions
|
@ -1068,7 +1068,6 @@ set (PCH_SOURCES
|
||||||
rendering/gl/renderer/gl_scene.cpp
|
rendering/gl/renderer/gl_scene.cpp
|
||||||
rendering/gl/shaders/gl_shader.cpp
|
rendering/gl/shaders/gl_shader.cpp
|
||||||
rendering/gl/shaders/gl_shaderprogram.cpp
|
rendering/gl/shaders/gl_shaderprogram.cpp
|
||||||
rendering/gl/shaders/gl_postprocessshader.cpp
|
|
||||||
rendering/gl_load/gl_interface.cpp
|
rendering/gl_load/gl_interface.cpp
|
||||||
rendering/gl/system/gl_framebuffer.cpp
|
rendering/gl/system/gl_framebuffer.cpp
|
||||||
rendering/gl/system/gl_debug.cpp
|
rendering/gl/system/gl_debug.cpp
|
||||||
|
|
|
@ -43,7 +43,6 @@
|
||||||
#include "hwrenderer/postprocessing/hw_postprocess_cvars.h"
|
#include "hwrenderer/postprocessing/hw_postprocess_cvars.h"
|
||||||
#include "hwrenderer/utility/hw_vrmodes.h"
|
#include "hwrenderer/utility/hw_vrmodes.h"
|
||||||
#include "hwrenderer/data/flatvertices.h"
|
#include "hwrenderer/data/flatvertices.h"
|
||||||
#include "gl/shaders/gl_postprocessshaderinstance.h"
|
|
||||||
#include "gl/textures/gl_hwtexture.h"
|
#include "gl/textures/gl_hwtexture.h"
|
||||||
#include "r_videoscale.h"
|
#include "r_videoscale.h"
|
||||||
|
|
||||||
|
@ -70,7 +69,7 @@ void FGLRenderer::PostProcessScene(int fixedcm, const std::function<void()> &aft
|
||||||
GLPPRenderState renderstate(mBuffers);
|
GLPPRenderState renderstate(mBuffers);
|
||||||
|
|
||||||
hw_postprocess.exposure.Render(&renderstate, sceneWidth, sceneHeight);
|
hw_postprocess.exposure.Render(&renderstate, sceneWidth, sceneHeight);
|
||||||
mCustomPostProcessShaders->Run("beforebloom");
|
hw_postprocess.customShaders.Run(&renderstate, "beforebloom");
|
||||||
hw_postprocess.bloom.RenderBloom(&renderstate, sceneWidth, sceneHeight, fixedcm);
|
hw_postprocess.bloom.RenderBloom(&renderstate, sceneWidth, sceneHeight, fixedcm);
|
||||||
|
|
||||||
mBuffers->BindCurrentFB();
|
mBuffers->BindCurrentFB();
|
||||||
|
@ -80,7 +79,7 @@ void FGLRenderer::PostProcessScene(int fixedcm, const std::function<void()> &aft
|
||||||
hw_postprocess.colormap.Render(&renderstate, fixedcm);
|
hw_postprocess.colormap.Render(&renderstate, fixedcm);
|
||||||
hw_postprocess.lens.Render(&renderstate);
|
hw_postprocess.lens.Render(&renderstate);
|
||||||
hw_postprocess.fxaa.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->Draw2D(); // draw all pending 2D stuff before copying the buffer
|
||||||
screen->Clear2D();
|
screen->Clear2D();
|
||||||
|
|
||||||
mCustomPostProcessShaders->Run("screen");
|
GLPPRenderState renderstate(mBuffers);
|
||||||
|
hw_postprocess.customShaders.Run(&renderstate, "screen");
|
||||||
|
|
||||||
FGLDebug::PushGroup("CopyToBackbuffer");
|
FGLDebug::PushGroup("CopyToBackbuffer");
|
||||||
FGLPostProcessState savedState;
|
FGLPostProcessState savedState;
|
||||||
|
|
|
@ -52,7 +52,6 @@
|
||||||
#include "hwrenderer/data/flatvertices.h"
|
#include "hwrenderer/data/flatvertices.h"
|
||||||
#include "hwrenderer/scene/hw_skydome.h"
|
#include "hwrenderer/scene/hw_skydome.h"
|
||||||
#include "hwrenderer/scene/hw_fakeflat.h"
|
#include "hwrenderer/scene/hw_fakeflat.h"
|
||||||
#include "gl/shaders/gl_postprocessshaderinstance.h"
|
|
||||||
#include "gl/textures/gl_samplers.h"
|
#include "gl/textures/gl_samplers.h"
|
||||||
#include "hwrenderer/dynlights/hw_lightbuffer.h"
|
#include "hwrenderer/dynlights/hw_lightbuffer.h"
|
||||||
#include "hwrenderer/data/hw_viewpointbuffer.h"
|
#include "hwrenderer/data/hw_viewpointbuffer.h"
|
||||||
|
@ -97,7 +96,6 @@ void FGLRenderer::Initialize(int width, int height)
|
||||||
mPresent3dColumnShader = new FPresent3DColumnShader();
|
mPresent3dColumnShader = new FPresent3DColumnShader();
|
||||||
mPresent3dRowShader = new FPresent3DRowShader();
|
mPresent3dRowShader = new FPresent3DRowShader();
|
||||||
mShadowMapShader = new FShadowMapShader();
|
mShadowMapShader = new FShadowMapShader();
|
||||||
mCustomPostProcessShaders = new FCustomPostProcessShaders();
|
|
||||||
|
|
||||||
// needed for the core profile, because someone decided it was a good idea to remove the default VAO.
|
// needed for the core profile, because someone decided it was a good idea to remove the default VAO.
|
||||||
glGenQueries(1, &PortalQueryObject);
|
glGenQueries(1, &PortalQueryObject);
|
||||||
|
@ -135,7 +133,6 @@ FGLRenderer::~FGLRenderer()
|
||||||
if (mPresent3dColumnShader) delete mPresent3dColumnShader;
|
if (mPresent3dColumnShader) delete mPresent3dColumnShader;
|
||||||
if (mPresent3dRowShader) delete mPresent3dRowShader;
|
if (mPresent3dRowShader) delete mPresent3dRowShader;
|
||||||
if (mShadowMapShader) delete mShadowMapShader;
|
if (mShadowMapShader) delete mShadowMapShader;
|
||||||
delete mCustomPostProcessShaders;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
|
@ -33,7 +33,6 @@ struct FRenderViewpoint;
|
||||||
namespace OpenGLRenderer
|
namespace OpenGLRenderer
|
||||||
{
|
{
|
||||||
class FSamplerManager;
|
class FSamplerManager;
|
||||||
class FCustomPostProcessShaders;
|
|
||||||
class OpenGLFrameBuffer;
|
class OpenGLFrameBuffer;
|
||||||
class FPresentShaderBase;
|
class FPresentShaderBase;
|
||||||
class FPresentShader;
|
class FPresentShader;
|
||||||
|
@ -66,7 +65,6 @@ public:
|
||||||
FPresent3DColumnShader *mPresent3dColumnShader = nullptr;
|
FPresent3DColumnShader *mPresent3dColumnShader = nullptr;
|
||||||
FPresent3DRowShader *mPresent3dRowShader = nullptr;
|
FPresent3DRowShader *mPresent3dRowShader = nullptr;
|
||||||
FShadowMapShader *mShadowMapShader = nullptr;
|
FShadowMapShader *mShadowMapShader = nullptr;
|
||||||
FCustomPostProcessShaders *mCustomPostProcessShaders = nullptr;
|
|
||||||
|
|
||||||
//FRotator mAngles;
|
//FRotator mAngles;
|
||||||
|
|
||||||
|
|
|
@ -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<PostProcessShaderInstance>(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<FString, PostProcessUniformValue>::Iterator it(Desc->Uniforms);
|
|
||||||
TMap<FString, PostProcessUniformValue>::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<FString, FString>::Iterator itTextures(Desc->Textures);
|
|
||||||
TMap<FString, FString>::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<FString, PostProcessUniformValue>::Iterator it(Desc->Uniforms);
|
|
||||||
TMap<FString, PostProcessUniformValue>::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<FString, FString>::Iterator it(Desc->Textures);
|
|
||||||
TMap<FString, FString>::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++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,49 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "gl_shaderprogram.h"
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
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<FTexture*, int> mTextureHandles;
|
|
||||||
};
|
|
||||||
|
|
||||||
class FCustomPostProcessShaders
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
FCustomPostProcessShaders();
|
|
||||||
~FCustomPostProcessShaders();
|
|
||||||
|
|
||||||
void Run(FString target);
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<std::unique_ptr<PostProcessShaderInstance>> mShaders;
|
|
||||||
|
|
||||||
FCustomPostProcessShaders(const FCustomPostProcessShaders &) = delete;
|
|
||||||
FCustomPostProcessShaders &operator=(const FCustomPostProcessShaders &) = delete;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -91,7 +91,7 @@ void FShaderProgram::CreateShader(ShaderType type)
|
||||||
|
|
||||||
void FShaderProgram::Compile(ShaderType type, const char *lumpName, const char *defines, int maxGlslVersion)
|
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);
|
if (lump == -1) I_FatalError("Unable to load '%s'", lumpName);
|
||||||
FString code = Wads.ReadLump(lump).GetString().GetChars();
|
FString code = Wads.ReadLump(lump).GetString().GetChars();
|
||||||
Compile(type, lumpName, code, defines, maxGlslVersion);
|
Compile(type, lumpName, code, defines, maxGlslVersion);
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "hw_postprocess.h"
|
#include "hw_postprocess.h"
|
||||||
#include "hwrenderer/utility/hw_cvars.h"
|
#include "hwrenderer/utility/hw_cvars.h"
|
||||||
#include "hwrenderer/postprocessing/hw_postprocess_cvars.h"
|
#include "hwrenderer/postprocessing/hw_postprocess_cvars.h"
|
||||||
|
#include "hwrenderer/postprocessing/hw_postprocessshader.h"
|
||||||
#include <random>
|
#include <random>
|
||||||
|
|
||||||
Postprocess hw_postprocess;
|
Postprocess hw_postprocess;
|
||||||
|
@ -443,7 +444,10 @@ void PPCameraExposure::Render(PPRenderState *renderstate, int sceneWidth, int sc
|
||||||
|
|
||||||
void PPCameraExposure::UpdateTextures(int width, int height)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -802,3 +806,203 @@ void PPShadowMap::Update(PPRenderState *renderstate)
|
||||||
renderstate->SetNoBlend();
|
renderstate->SetNoBlend();
|
||||||
renderstate->Draw();
|
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<PPCustomShaderInstance>(&PostProcessShaders[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
PPCustomShaderInstance::PPCustomShaderInstance(PostProcessShader *desc) : Desc(desc)
|
||||||
|
{
|
||||||
|
// Build an uniform block to be used as input
|
||||||
|
TMap<FString, PostProcessUniformValue>::Iterator it(Desc->Uniforms);
|
||||||
|
TMap<FString, PostProcessUniformValue>::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<FString, FString>::Iterator itTextures(Desc->Textures);
|
||||||
|
TMap<FString, FString>::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<FString, FString>::Iterator it(Desc->Textures);
|
||||||
|
TMap<FString, FString>::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<void> 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<PPTexture>(buffer.mWidth, buffer.mHeight, PixelFormat::Rgba8, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderstate->SetInputTexture(textureIndex, pptex.get(), PPFilterMode::Linear);
|
||||||
|
textureIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PPCustomShaderInstance::SetUniforms(PPRenderState *renderstate)
|
||||||
|
{
|
||||||
|
TArray<uint8_t> uniforms;
|
||||||
|
uniforms.Resize(UniformStructSize);
|
||||||
|
|
||||||
|
TMap<FString, PostProcessUniformValue>::Iterator it(Desc->Uniforms);
|
||||||
|
TMap<FString, PostProcessUniformValue>::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<FString>(name);
|
||||||
|
FieldNames.push_back(std::move(name2));
|
||||||
|
Fields.push_back({ name2->GetChars(), type, offset });
|
||||||
|
|
||||||
|
offset += fieldsize;
|
||||||
|
}
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
|
|
||||||
#include "hwrenderer/data/shaderuniforms.h"
|
#include "hwrenderer/data/shaderuniforms.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
struct PostProcessShader;
|
||||||
|
|
||||||
typedef FRenderStyle PPBlendMode;
|
typedef FRenderStyle PPBlendMode;
|
||||||
typedef IntRect PPViewport;
|
typedef IntRect PPViewport;
|
||||||
|
@ -292,7 +295,7 @@ public:
|
||||||
class PPShader : public PPResource
|
class PPShader : public PPResource
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PPShader() { }
|
PPShader() = default;
|
||||||
PPShader(const FString &fragment, const FString &defines, const std::vector<UniformFieldDesc> &uniforms, int version = 330) : FragmentShader(fragment), Defines(defines), Uniforms(uniforms), Version(version) { }
|
PPShader(const FString &fragment, const FString &defines, const std::vector<UniformFieldDesc> &uniforms, int version = 330) : FragmentShader(fragment), Defines(defines), Uniforms(uniforms), Version(version) { }
|
||||||
|
|
||||||
void ResetBackend() override { Backend.reset(); }
|
void ResetBackend() override { Backend.reset(); }
|
||||||
|
@ -777,6 +780,40 @@ private:
|
||||||
PPShader ShadowMap = { "shaders/glsl/shadowmap.fp", "", ShadowMapUniforms::Desc() };
|
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<UniformFieldDesc> Fields;
|
||||||
|
std::vector<std::unique_ptr<FString>> FieldNames;
|
||||||
|
std::map<FTexture*, std::unique_ptr<PPTexture>> Textures;
|
||||||
|
std::map<FString, size_t> FieldOffset;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PPCustomShaders
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void Run(PPRenderState *renderstate, FString target);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void CreateShaders();
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<PPCustomShaderInstance>> mShaders;
|
||||||
|
};
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
class Postprocess
|
class Postprocess
|
||||||
|
@ -791,6 +828,7 @@ public:
|
||||||
PPAmbientOcclusion ssao;
|
PPAmbientOcclusion ssao;
|
||||||
PPPresent present;
|
PPPresent present;
|
||||||
PPShadowMap shadowmap;
|
PPShadowMap shadowmap;
|
||||||
|
PPCustomShaders customShaders;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Postprocess hw_postprocess;
|
extern Postprocess hw_postprocess;
|
||||||
|
|
|
@ -46,7 +46,7 @@ void VkPostprocess::PostProcessScene(int fixedcm, const std::function<void()> &a
|
||||||
VkPPRenderState renderstate;
|
VkPPRenderState renderstate;
|
||||||
|
|
||||||
hw_postprocess.exposure.Render(&renderstate, sceneWidth, sceneHeight);
|
hw_postprocess.exposure.Render(&renderstate, sceneWidth, sceneHeight);
|
||||||
//mCustomPostProcessShaders->Run("beforebloom");
|
hw_postprocess.customShaders.Run(&renderstate, "beforebloom");
|
||||||
hw_postprocess.bloom.RenderBloom(&renderstate, sceneWidth, sceneHeight, fixedcm);
|
hw_postprocess.bloom.RenderBloom(&renderstate, sceneWidth, sceneHeight, fixedcm);
|
||||||
|
|
||||||
SetActiveRenderTarget();
|
SetActiveRenderTarget();
|
||||||
|
@ -56,7 +56,7 @@ void VkPostprocess::PostProcessScene(int fixedcm, const std::function<void()> &a
|
||||||
hw_postprocess.colormap.Render(&renderstate, fixedcm);
|
hw_postprocess.colormap.Render(&renderstate, fixedcm);
|
||||||
hw_postprocess.lens.Render(&renderstate);
|
hw_postprocess.lens.Render(&renderstate);
|
||||||
hw_postprocess.fxaa.Render(&renderstate);
|
hw_postprocess.fxaa.Render(&renderstate);
|
||||||
//mCustomPostProcessShaders->Run("scene");
|
hw_postprocess.customShaders.Run(&renderstate, "scene");
|
||||||
}
|
}
|
||||||
|
|
||||||
void VkPostprocess::BlitSceneToPostprocess()
|
void VkPostprocess::BlitSceneToPostprocess()
|
||||||
|
@ -175,6 +175,9 @@ void VkPostprocess::DrawPresentTexture(const IntRect &box, bool applyGamma, bool
|
||||||
{
|
{
|
||||||
auto fb = GetVulkanFrameBuffer();
|
auto fb = GetVulkanFrameBuffer();
|
||||||
|
|
||||||
|
VkPPRenderState renderstate;
|
||||||
|
hw_postprocess.customShaders.Run(&renderstate, "screen");
|
||||||
|
|
||||||
PresentUniforms uniforms;
|
PresentUniforms uniforms;
|
||||||
if (!applyGamma /*|| framebuffer->IsHWGammaActive()*/)
|
if (!applyGamma /*|| framebuffer->IsHWGammaActive()*/)
|
||||||
{
|
{
|
||||||
|
@ -200,7 +203,7 @@ void VkPostprocess::DrawPresentTexture(const IntRect &box, bool applyGamma, bool
|
||||||
uniforms.InvGamma *= 2.2f;
|
uniforms.InvGamma *= 2.2f;
|
||||||
}
|
}
|
||||||
|
|
||||||
VkPPRenderState renderstate;
|
renderstate.Clear();
|
||||||
renderstate.Shader = &hw_postprocess.present.Present;
|
renderstate.Shader = &hw_postprocess.present.Present;
|
||||||
renderstate.Uniforms.Set(uniforms);
|
renderstate.Uniforms.Set(uniforms);
|
||||||
renderstate.Viewport = box;
|
renderstate.Viewport = box;
|
||||||
|
@ -266,8 +269,6 @@ void VkPostprocess::UpdateShadowMap()
|
||||||
|
|
||||||
void VkPostprocess::BeginFrame()
|
void VkPostprocess::BeginFrame()
|
||||||
{
|
{
|
||||||
mFrameDescriptorSets.clear();
|
|
||||||
|
|
||||||
if (!mDescriptorPool)
|
if (!mDescriptorPool)
|
||||||
{
|
{
|
||||||
DescriptorPoolBuilder builder;
|
DescriptorPoolBuilder builder;
|
||||||
|
@ -533,8 +534,9 @@ VulkanDescriptorSet *VkPPRenderState::GetInput(VkPPRenderPassSetup *passSetup, c
|
||||||
write.updateSets(fb->device);
|
write.updateSets(fb->device);
|
||||||
imageTransition.execute(fb->GetDrawCommands());
|
imageTransition.execute(fb->GetDrawCommands());
|
||||||
|
|
||||||
pp->mFrameDescriptorSets.push_back(std::move(descriptors));
|
VulkanDescriptorSet *set = descriptors.get();
|
||||||
return pp->mFrameDescriptorSets.back().get();
|
fb->FrameDeleteList.Descriptors.push_back(std::move(descriptors));
|
||||||
|
return set;
|
||||||
}
|
}
|
||||||
|
|
||||||
VulkanFramebuffer *VkPPRenderState::GetOutput(VkPPRenderPassSetup *passSetup, const PPOutput &output, int &framebufferWidth, int &framebufferHeight)
|
VulkanFramebuffer *VkPPRenderState::GetOutput(VkPPRenderPassSetup *passSetup, const PPOutput &output, int &framebufferWidth, int &framebufferHeight)
|
||||||
|
|
|
@ -78,7 +78,6 @@ private:
|
||||||
std::array<std::unique_ptr<VulkanSampler>, 16> mSamplers;
|
std::array<std::unique_ptr<VulkanSampler>, 16> mSamplers;
|
||||||
std::map<VkPPRenderPassKey, std::unique_ptr<VkPPRenderPassSetup>> mRenderPassSetup;
|
std::map<VkPPRenderPassKey, std::unique_ptr<VkPPRenderPassSetup>> mRenderPassSetup;
|
||||||
std::unique_ptr<VulkanDescriptorPool> mDescriptorPool;
|
std::unique_ptr<VulkanDescriptorPool> mDescriptorPool;
|
||||||
std::vector<std::unique_ptr<VulkanDescriptorSet>> mFrameDescriptorSets;
|
|
||||||
int mCurrentPipelineImage = 0;
|
int mCurrentPipelineImage = 0;
|
||||||
|
|
||||||
friend class VkPPRenderState;
|
friend class VkPPRenderState;
|
||||||
|
|
Loading…
Reference in a new issue