mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2025-02-07 15:31:02 +00:00
- convert PPStep to PPRenderState
This commit is contained in:
parent
cce96ca87a
commit
05f0730c9d
10 changed files with 988 additions and 999 deletions
|
@ -64,26 +64,22 @@ void FGLRenderer::RenderScreenQuad()
|
||||||
|
|
||||||
void FGLRenderer::PostProcessScene(int fixedcm, const std::function<void()> &afterBloomDrawEndScene2D)
|
void FGLRenderer::PostProcessScene(int fixedcm, const std::function<void()> &afterBloomDrawEndScene2D)
|
||||||
{
|
{
|
||||||
hw_postprocess.fixedcm = fixedcm;
|
int sceneWidth = mBuffers->GetSceneWidth();
|
||||||
hw_postprocess.SceneWidth = mBuffers->GetSceneWidth();
|
int sceneHeight = mBuffers->GetSceneHeight();
|
||||||
hw_postprocess.SceneHeight = mBuffers->GetSceneHeight();
|
|
||||||
|
|
||||||
hw_postprocess.DeclareShaders();
|
GLPPRenderState renderstate(mBuffers);
|
||||||
hw_postprocess.UpdateTextures();
|
|
||||||
hw_postprocess.UpdateSteps();
|
|
||||||
|
|
||||||
mBuffers->CompileEffectShaders();
|
hw_postprocess.exposure.Render(&renderstate, sceneWidth, sceneHeight);
|
||||||
mBuffers->UpdateEffectTextures();
|
|
||||||
|
|
||||||
mBuffers->RenderEffect("UpdateCameraExposure");
|
|
||||||
mCustomPostProcessShaders->Run("beforebloom");
|
mCustomPostProcessShaders->Run("beforebloom");
|
||||||
mBuffers->RenderEffect("BloomScene");
|
hw_postprocess.bloom.RenderBloom(&renderstate, sceneWidth, sceneHeight, fixedcm);
|
||||||
|
|
||||||
mBuffers->BindCurrentFB();
|
mBuffers->BindCurrentFB();
|
||||||
afterBloomDrawEndScene2D();
|
afterBloomDrawEndScene2D();
|
||||||
mBuffers->RenderEffect("TonemapScene");
|
|
||||||
mBuffers->RenderEffect("ColormapScene");
|
hw_postprocess.tonemap.Render(&renderstate);
|
||||||
mBuffers->RenderEffect("LensDistortScene");
|
hw_postprocess.colormap.Render(&renderstate, fixedcm);
|
||||||
mBuffers->RenderEffect("ApplyFXAA");
|
hw_postprocess.lens.Render(&renderstate);
|
||||||
|
hw_postprocess.fxaa.Render(&renderstate);
|
||||||
mCustomPostProcessShaders->Run("scene");
|
mCustomPostProcessShaders->Run("scene");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,43 +91,32 @@ void FGLRenderer::PostProcessScene(int fixedcm, const std::function<void()> &aft
|
||||||
|
|
||||||
void FGLRenderer::AmbientOccludeScene(float m5)
|
void FGLRenderer::AmbientOccludeScene(float m5)
|
||||||
{
|
{
|
||||||
hw_postprocess.SceneWidth = mBuffers->GetSceneWidth();
|
int sceneWidth = mBuffers->GetSceneWidth();
|
||||||
hw_postprocess.SceneHeight = mBuffers->GetSceneHeight();
|
int sceneHeight = mBuffers->GetSceneHeight();
|
||||||
hw_postprocess.m5 = m5;
|
|
||||||
|
|
||||||
hw_postprocess.DeclareShaders();
|
GLPPRenderState renderstate(mBuffers);
|
||||||
hw_postprocess.UpdateTextures();
|
hw_postprocess.ssao.Render(&renderstate, m5, sceneWidth, sceneHeight);
|
||||||
hw_postprocess.UpdateSteps();
|
|
||||||
|
|
||||||
mBuffers->CompileEffectShaders();
|
|
||||||
mBuffers->UpdateEffectTextures();
|
|
||||||
|
|
||||||
mBuffers->RenderEffect("AmbientOccludeScene");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGLRenderer::BlurScene(float gameinfobluramount)
|
void FGLRenderer::BlurScene(float gameinfobluramount)
|
||||||
{
|
{
|
||||||
hw_postprocess.gameinfobluramount = gameinfobluramount;
|
int sceneWidth = mBuffers->GetSceneWidth();
|
||||||
|
int sceneHeight = mBuffers->GetSceneHeight();
|
||||||
|
|
||||||
hw_postprocess.DeclareShaders();
|
GLPPRenderState renderstate(mBuffers);
|
||||||
hw_postprocess.UpdateTextures();
|
|
||||||
hw_postprocess.UpdateSteps();
|
|
||||||
|
|
||||||
mBuffers->CompileEffectShaders();
|
|
||||||
mBuffers->UpdateEffectTextures();
|
|
||||||
|
|
||||||
auto vrmode = VRMode::GetVRMode(true);
|
auto vrmode = VRMode::GetVRMode(true);
|
||||||
int eyeCount = vrmode->mEyeCount;
|
int eyeCount = vrmode->mEyeCount;
|
||||||
for (int i = 0; i < eyeCount; ++i)
|
for (int i = 0; i < eyeCount; ++i)
|
||||||
{
|
{
|
||||||
mBuffers->RenderEffect("BlurScene");
|
hw_postprocess.bloom.RenderBlur(&renderstate, sceneWidth, sceneHeight, gameinfobluramount);
|
||||||
if (eyeCount - i > 1) mBuffers->NextEye(eyeCount);
|
if (eyeCount - i > 1) mBuffers->NextEye(eyeCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGLRenderer::ClearTonemapPalette()
|
void FGLRenderer::ClearTonemapPalette()
|
||||||
{
|
{
|
||||||
hw_postprocess.Textures.Remove("Tonemap.Palette");
|
hw_postprocess.tonemap.ClearTonemapPalette();
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
|
@ -792,19 +792,16 @@ bool FGLRenderBuffers::FailedCreate = false;
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void FGLRenderBuffers::UpdateEffectTextures()
|
PPGLTextureBackend *GLPPRenderState::GetGLTexture(PPTexture *texture)
|
||||||
{
|
{
|
||||||
FGLPostProcessState savedState;
|
if (!texture->Backend)
|
||||||
|
|
||||||
TMap<FString, PPTextureDesc>::Iterator it(hw_postprocess.Textures);
|
|
||||||
TMap<FString, PPTextureDesc>::Pair *pair;
|
|
||||||
while (it.NextPair(pair))
|
|
||||||
{
|
{
|
||||||
auto &gltexture = GLTextures[pair->Key];
|
FGLPostProcessState savedState;
|
||||||
auto &glframebuffer = GLTextureFBs[pair->Key];
|
|
||||||
|
auto backend = std::make_unique<PPGLTextureBackend>();
|
||||||
|
|
||||||
int glformat;
|
int glformat;
|
||||||
switch (pair->Value.Format)
|
switch (texture->Format)
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
case PixelFormat::Rgba8: glformat = GL_RGBA8; break;
|
case PixelFormat::Rgba8: glformat = GL_RGBA8; break;
|
||||||
|
@ -814,28 +811,14 @@ void FGLRenderBuffers::UpdateEffectTextures()
|
||||||
case PixelFormat::Rgba16_snorm: glformat = GL_RGBA16_SNORM; break;
|
case PixelFormat::Rgba16_snorm: glformat = GL_RGBA16_SNORM; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gltexture && (gltexture.Width != pair->Value.Width || gltexture.Height != pair->Value.Height))
|
if (texture->Data)
|
||||||
{
|
backend->Tex = buffers->Create2DTexture("PPTexture", glformat, texture->Width, texture->Height, texture->Data.get());
|
||||||
if (gltexture.handle != 0)
|
else
|
||||||
{
|
backend->Tex = buffers->Create2DTexture("PPTexture", glformat, texture->Width, texture->Height);
|
||||||
glDeleteTextures(1, &gltexture.handle);
|
|
||||||
gltexture.handle = 0;
|
|
||||||
}
|
|
||||||
if (glframebuffer.handle != 0)
|
|
||||||
{
|
|
||||||
glDeleteFramebuffers(1, &glframebuffer.handle);
|
|
||||||
glframebuffer.handle = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!gltexture)
|
texture->Backend = std::move(backend);
|
||||||
{
|
|
||||||
if (pair->Value.Data)
|
|
||||||
gltexture = Create2DTexture(pair->Key.GetChars(), glformat, pair->Value.Width, pair->Value.Height, pair->Value.Data.get());
|
|
||||||
else
|
|
||||||
gltexture = Create2DTexture(pair->Key.GetChars(), glformat, pair->Value.Width, pair->Value.Height);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return static_cast<PPGLTextureBackend*>(texture->Backend.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -844,30 +827,26 @@ void FGLRenderBuffers::UpdateEffectTextures()
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void FGLRenderBuffers::CompileEffectShaders()
|
FShaderProgram *GLPPRenderState::GetGLShader(PPShader *shader)
|
||||||
{
|
{
|
||||||
TMap<FString, PPShader>::Iterator it(hw_postprocess.Shaders);
|
if (!shader->Backend)
|
||||||
TMap<FString, PPShader>::Pair *pair;
|
|
||||||
while (it.NextPair(pair))
|
|
||||||
{
|
{
|
||||||
const auto &desc = pair->Value;
|
auto glshader = std::make_unique<FShaderProgram>();
|
||||||
auto &glshader = GLShaders[pair->Key];
|
|
||||||
if (!glshader)
|
|
||||||
{
|
|
||||||
glshader = std::make_unique<FShaderProgram>();
|
|
||||||
|
|
||||||
FString prolog;
|
FString prolog;
|
||||||
if (!desc.Uniforms.empty())
|
if (!shader->Uniforms.empty())
|
||||||
prolog = UniformBlockDecl::Create("Uniforms", desc.Uniforms, POSTPROCESS_BINDINGPOINT);
|
prolog = UniformBlockDecl::Create("Uniforms", shader->Uniforms, POSTPROCESS_BINDINGPOINT);
|
||||||
prolog += desc.Defines;
|
prolog += shader->Defines;
|
||||||
|
|
||||||
glshader->Compile(FShaderProgram::Vertex, desc.VertexShader, "", desc.Version);
|
glshader->Compile(FShaderProgram::Vertex, shader->VertexShader, "", shader->Version);
|
||||||
glshader->Compile(FShaderProgram::Fragment, desc.FragmentShader, prolog, desc.Version);
|
glshader->Compile(FShaderProgram::Fragment, shader->FragmentShader, prolog, shader->Version);
|
||||||
glshader->Link(pair->Key.GetChars());
|
glshader->Link(shader->FragmentShader.GetChars());
|
||||||
if (!desc.Uniforms.empty())
|
if (!shader->Uniforms.empty())
|
||||||
glshader->SetUniformBufferLocation(POSTPROCESS_BINDINGPOINT, "Uniforms");
|
glshader->SetUniformBufferLocation(POSTPROCESS_BINDINGPOINT, "Uniforms");
|
||||||
}
|
|
||||||
|
shader->Backend = std::move(glshader);
|
||||||
}
|
}
|
||||||
|
return static_cast<FShaderProgram*>(shader->Backend.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -876,130 +855,124 @@ void FGLRenderBuffers::CompileEffectShaders()
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void FGLRenderBuffers::RenderEffect(const FString &name)
|
void GLPPRenderState::Draw()
|
||||||
{
|
{
|
||||||
if (hw_postprocess.Effects[name].Size() == 0)
|
//FGLDebug::PushGroup(name.GetChars());
|
||||||
return;
|
|
||||||
|
|
||||||
FGLDebug::PushGroup(name.GetChars());
|
|
||||||
|
|
||||||
FGLPostProcessState savedState;
|
FGLPostProcessState savedState;
|
||||||
|
|
||||||
for (const PPStep &step : hw_postprocess.Effects[name])
|
// Bind input textures
|
||||||
|
for (unsigned int index = 0; index < Textures.Size(); index++)
|
||||||
{
|
{
|
||||||
// Bind input textures
|
savedState.SaveTextureBindings(index + 1);
|
||||||
for (unsigned int index = 0; index < step.Textures.Size(); index++)
|
|
||||||
{
|
|
||||||
savedState.SaveTextureBindings(index + 1);
|
|
||||||
|
|
||||||
const PPTextureInput &input = step.Textures[index];
|
const PPTextureInput &input = Textures[index];
|
||||||
int filter = (input.Filter == PPFilterMode::Nearest) ? GL_NEAREST : GL_LINEAR;
|
int filter = (input.Filter == PPFilterMode::Nearest) ? GL_NEAREST : GL_LINEAR;
|
||||||
int wrap = (input.Wrap == PPWrapMode::Clamp) ? GL_CLAMP : GL_REPEAT;
|
int wrap = (input.Wrap == PPWrapMode::Clamp) ? GL_CLAMP : GL_REPEAT;
|
||||||
|
|
||||||
switch (input.Type)
|
switch (input.Type)
|
||||||
{
|
|
||||||
default:
|
|
||||||
case PPTextureType::CurrentPipelineTexture:
|
|
||||||
BindCurrentTexture(index, filter, wrap);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PPTextureType::NextPipelineTexture:
|
|
||||||
I_FatalError("PPTextureType::NextPipelineTexture not allowed as input\n");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PPTextureType::PPTexture:
|
|
||||||
GLTextures[input.Texture].Bind(index, filter, wrap);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PPTextureType::SceneColor:
|
|
||||||
BindSceneColorTexture(index);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PPTextureType::SceneFog:
|
|
||||||
BindSceneFogTexture(index);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PPTextureType::SceneNormal:
|
|
||||||
BindSceneNormalTexture(index);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PPTextureType::SceneDepth:
|
|
||||||
BindSceneDepthTexture(index);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set render target
|
|
||||||
switch (step.Output.Type)
|
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
I_FatalError("Unsupported postprocess output type\n");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PPTextureType::CurrentPipelineTexture:
|
case PPTextureType::CurrentPipelineTexture:
|
||||||
BindCurrentFB();
|
buffers->BindCurrentTexture(index, filter, wrap);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PPTextureType::NextPipelineTexture:
|
case PPTextureType::NextPipelineTexture:
|
||||||
BindNextFB();
|
I_FatalError("PPTextureType::NextPipelineTexture not allowed as input\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PPTextureType::PPTexture:
|
case PPTextureType::PPTexture:
|
||||||
if (GLTextureFBs[step.Output.Texture])
|
GetGLTexture(input.Texture)->Tex.Bind(index, filter, wrap);
|
||||||
GLTextureFBs[step.Output.Texture].Bind();
|
|
||||||
else
|
|
||||||
GLTextureFBs[step.Output.Texture] = CreateFrameBuffer(step.Output.Texture.GetChars(), GLTextures[step.Output.Texture]);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PPTextureType::SceneColor:
|
case PPTextureType::SceneColor:
|
||||||
BindSceneFB(false);
|
buffers->BindSceneColorTexture(index);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PPTextureType::SceneFog:
|
||||||
|
buffers->BindSceneFogTexture(index);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PPTextureType::SceneNormal:
|
||||||
|
buffers->BindSceneNormalTexture(index);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PPTextureType::SceneDepth:
|
||||||
|
buffers->BindSceneDepthTexture(index);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set blend mode
|
|
||||||
if (step.BlendMode.BlendOp == STYLEOP_Add && step.BlendMode.SrcAlpha == STYLEALPHA_One && step.BlendMode.DestAlpha == STYLEALPHA_Zero && step.BlendMode.Flags == 0)
|
|
||||||
{
|
|
||||||
glDisable(GL_BLEND);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// To do: support all the modes
|
|
||||||
glEnable(GL_BLEND);
|
|
||||||
glBlendEquation(GL_FUNC_ADD);
|
|
||||||
if (step.BlendMode.SrcAlpha == STYLEALPHA_One && step.BlendMode.DestAlpha == STYLEALPHA_One)
|
|
||||||
glBlendFunc(GL_ONE, GL_ONE);
|
|
||||||
else
|
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup viewport
|
|
||||||
glViewport(step.Viewport.left, step.Viewport.top, step.Viewport.width, step.Viewport.height);
|
|
||||||
|
|
||||||
auto &shader = GLShaders[step.ShaderName];
|
|
||||||
|
|
||||||
// Set uniforms
|
|
||||||
if (step.Uniforms.Data.Size() > 0)
|
|
||||||
{
|
|
||||||
if (!shader->Uniforms)
|
|
||||||
shader->Uniforms.reset(screen->CreateDataBuffer(POSTPROCESS_BINDINGPOINT, false));
|
|
||||||
shader->Uniforms->SetData(step.Uniforms.Data.Size(), step.Uniforms.Data.Data());
|
|
||||||
shader->Uniforms->BindBase();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set shader
|
|
||||||
shader->Bind();
|
|
||||||
|
|
||||||
// Draw the screen quad
|
|
||||||
GLRenderer->RenderScreenQuad();
|
|
||||||
|
|
||||||
// Advance to next PP texture if our output was sent there
|
|
||||||
if (step.Output.Type == PPTextureType::NextPipelineTexture)
|
|
||||||
NextTexture();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set render target
|
||||||
|
switch (Output.Type)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
I_FatalError("Unsupported postprocess output type\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PPTextureType::CurrentPipelineTexture:
|
||||||
|
buffers->BindCurrentFB();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PPTextureType::NextPipelineTexture:
|
||||||
|
buffers->BindNextFB();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PPTextureType::PPTexture:
|
||||||
|
if (GetGLTexture(Output.Texture)->FB)
|
||||||
|
GetGLTexture(Output.Texture)->FB.Bind();
|
||||||
|
else
|
||||||
|
GetGLTexture(Output.Texture)->FB = buffers->CreateFrameBuffer("PPTextureFB"/*Output.Texture.GetChars()*/, GetGLTexture(Output.Texture)->Tex);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PPTextureType::SceneColor:
|
||||||
|
buffers->BindSceneFB(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set blend mode
|
||||||
|
if (BlendMode.BlendOp == STYLEOP_Add && BlendMode.SrcAlpha == STYLEALPHA_One && BlendMode.DestAlpha == STYLEALPHA_Zero && BlendMode.Flags == 0)
|
||||||
|
{
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// To do: support all the modes
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glBlendEquation(GL_FUNC_ADD);
|
||||||
|
if (BlendMode.SrcAlpha == STYLEALPHA_One && BlendMode.DestAlpha == STYLEALPHA_One)
|
||||||
|
glBlendFunc(GL_ONE, GL_ONE);
|
||||||
|
else
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup viewport
|
||||||
|
glViewport(Viewport.left, Viewport.top, Viewport.width, Viewport.height);
|
||||||
|
|
||||||
|
auto shader = GetGLShader(Shader);
|
||||||
|
|
||||||
|
// Set uniforms
|
||||||
|
if (Uniforms.Data.Size() > 0)
|
||||||
|
{
|
||||||
|
if (!shader->Uniforms)
|
||||||
|
shader->Uniforms.reset(screen->CreateDataBuffer(POSTPROCESS_BINDINGPOINT, false));
|
||||||
|
shader->Uniforms->SetData(Uniforms.Data.Size(), Uniforms.Data.Data());
|
||||||
|
shader->Uniforms->BindBase();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set shader
|
||||||
|
shader->Bind();
|
||||||
|
|
||||||
|
// Draw the screen quad
|
||||||
|
GLRenderer->RenderScreenQuad();
|
||||||
|
|
||||||
|
// Advance to next PP texture if our output was sent there
|
||||||
|
if (Output.Type == PPTextureType::NextPipelineTexture)
|
||||||
|
buffers->NextTexture();
|
||||||
|
|
||||||
glViewport(screen->mScreenViewport.left, screen->mScreenViewport.top, screen->mScreenViewport.width, screen->mScreenViewport.height);
|
glViewport(screen->mScreenViewport.left, screen->mScreenViewport.top, screen->mScreenViewport.width, screen->mScreenViewport.height);
|
||||||
|
|
||||||
FGLDebug::PopGroup();
|
//FGLDebug::PopGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@ private:
|
||||||
GLuint handle = 0;
|
GLuint handle = 0;
|
||||||
|
|
||||||
friend class FGLRenderBuffers;
|
friend class FGLRenderBuffers;
|
||||||
|
friend class PPGLTextureBackend;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PPGLFrameBuffer
|
class PPGLFrameBuffer
|
||||||
|
@ -45,6 +46,7 @@ private:
|
||||||
GLuint handle = 0;
|
GLuint handle = 0;
|
||||||
|
|
||||||
friend class FGLRenderBuffers;
|
friend class FGLRenderBuffers;
|
||||||
|
friend class PPGLTextureBackend;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PPGLRenderBuffer
|
class PPGLRenderBuffer
|
||||||
|
@ -57,8 +59,42 @@ private:
|
||||||
friend class FGLRenderBuffers;
|
friend class FGLRenderBuffers;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class PPGLTextureBackend : public PPTextureBackend
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
~PPGLTextureBackend()
|
||||||
|
{
|
||||||
|
if (Tex.handle != 0)
|
||||||
|
{
|
||||||
|
glDeleteTextures(1, &Tex.handle);
|
||||||
|
Tex.handle = 0;
|
||||||
|
}
|
||||||
|
if (FB.handle != 0)
|
||||||
|
{
|
||||||
|
glDeleteFramebuffers(1, &FB.handle);
|
||||||
|
FB.handle = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PPGLTexture Tex;
|
||||||
|
PPGLFrameBuffer FB;
|
||||||
|
};
|
||||||
|
|
||||||
class FShaderProgram;
|
class FShaderProgram;
|
||||||
|
|
||||||
|
class GLPPRenderState : public PPRenderState
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GLPPRenderState(FGLRenderBuffers *buffers) : buffers(buffers) { }
|
||||||
|
void Draw() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
PPGLTextureBackend *GetGLTexture(PPTexture *texture);
|
||||||
|
FShaderProgram *GetGLShader(PPShader *shader);
|
||||||
|
|
||||||
|
FGLRenderBuffers *buffers;
|
||||||
|
};
|
||||||
|
|
||||||
class FGLRenderBuffers
|
class FGLRenderBuffers
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -67,10 +103,6 @@ public:
|
||||||
|
|
||||||
void Setup(int width, int height, int sceneWidth, int sceneHeight);
|
void Setup(int width, int height, int sceneWidth, int sceneHeight);
|
||||||
|
|
||||||
void UpdateEffectTextures();
|
|
||||||
void CompileEffectShaders();
|
|
||||||
void RenderEffect(const FString &name);
|
|
||||||
|
|
||||||
void BindSceneFB(bool sceneData);
|
void BindSceneFB(bool sceneData);
|
||||||
void BindSceneColorTexture(int index);
|
void BindSceneColorTexture(int index);
|
||||||
void BindSceneFogTexture(int index);
|
void BindSceneFogTexture(int index);
|
||||||
|
@ -167,12 +199,9 @@ private:
|
||||||
|
|
||||||
PPGLTexture mDitherTexture;
|
PPGLTexture mDitherTexture;
|
||||||
|
|
||||||
// Postprocess OpenGL objects
|
|
||||||
TMap<PPTextureName, PPGLTexture> GLTextures;
|
|
||||||
TMap<PPTextureName, PPGLFrameBuffer> GLTextureFBs;
|
|
||||||
TMap<PPShaderName, std::shared_ptr<FShaderProgram>> GLShaders;
|
|
||||||
|
|
||||||
static bool FailedCreate;
|
static bool FailedCreate;
|
||||||
|
|
||||||
|
friend class GLPPRenderState;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
|
@ -8,7 +8,7 @@
|
||||||
namespace OpenGLRenderer
|
namespace OpenGLRenderer
|
||||||
{
|
{
|
||||||
|
|
||||||
class FShaderProgram
|
class FShaderProgram : public PPShaderBackend
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FShaderProgram();
|
FShaderProgram();
|
||||||
|
|
|
@ -87,6 +87,8 @@ OpenGLFrameBuffer::OpenGLFrameBuffer(void *hMonitor, bool fullscreen) :
|
||||||
|
|
||||||
OpenGLFrameBuffer::~OpenGLFrameBuffer()
|
OpenGLFrameBuffer::~OpenGLFrameBuffer()
|
||||||
{
|
{
|
||||||
|
PPResource::ResetAll();
|
||||||
|
|
||||||
if (mVertexData != nullptr) delete mVertexData;
|
if (mVertexData != nullptr) delete mVertexData;
|
||||||
if (mSkyData != nullptr) delete mSkyData;
|
if (mSkyData != nullptr) delete mSkyData;
|
||||||
if (mViewpoints != nullptr) delete mViewpoints;
|
if (mViewpoints != nullptr) delete mViewpoints;
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -3,12 +3,12 @@
|
||||||
#include "hwrenderer/data/shaderuniforms.h"
|
#include "hwrenderer/data/shaderuniforms.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
typedef FString PPTextureName;
|
|
||||||
typedef FString PPShaderName;
|
|
||||||
|
|
||||||
typedef FRenderStyle PPBlendMode;
|
typedef FRenderStyle PPBlendMode;
|
||||||
typedef IntRect PPViewport;
|
typedef IntRect PPViewport;
|
||||||
|
|
||||||
|
class PPTexture;
|
||||||
|
class PPShader;
|
||||||
|
|
||||||
enum class PPFilterMode { Nearest, Linear };
|
enum class PPFilterMode { Nearest, Linear };
|
||||||
enum class PPWrapMode { Clamp, Repeat };
|
enum class PPWrapMode { Clamp, Repeat };
|
||||||
enum class PPTextureType { CurrentPipelineTexture, NextPipelineTexture, PPTexture, SceneColor, SceneFog, SceneNormal, SceneDepth, SwapChain, ShadowMap };
|
enum class PPTextureType { CurrentPipelineTexture, NextPipelineTexture, PPTexture, SceneColor, SceneFog, SceneNormal, SceneDepth, SwapChain, ShadowMap };
|
||||||
|
@ -16,17 +16,17 @@ enum class PPTextureType { CurrentPipelineTexture, NextPipelineTexture, PPTextur
|
||||||
class PPTextureInput
|
class PPTextureInput
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PPFilterMode Filter;
|
PPFilterMode Filter = PPFilterMode::Nearest;
|
||||||
PPWrapMode Wrap;
|
PPWrapMode Wrap = PPWrapMode::Clamp;
|
||||||
PPTextureType Type;
|
PPTextureType Type = PPTextureType::CurrentPipelineTexture;
|
||||||
PPTextureName Texture;
|
PPTexture *Texture = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PPOutput
|
class PPOutput
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PPTextureType Type;
|
PPTextureType Type = PPTextureType::NextPipelineTexture;
|
||||||
PPTextureName Texture;
|
PPTexture *Texture = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PPUniforms
|
class PPUniforms
|
||||||
|
@ -70,10 +70,25 @@ public:
|
||||||
TArray<uint8_t> Data;
|
TArray<uint8_t> Data;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PPStep
|
class PPRenderState
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void SetInputTexture(int index, PPTextureName texture, PPFilterMode filter = PPFilterMode::Nearest, PPWrapMode wrap = PPWrapMode::Clamp)
|
virtual ~PPRenderState() = default;
|
||||||
|
|
||||||
|
virtual void Draw() = 0;
|
||||||
|
|
||||||
|
void Clear()
|
||||||
|
{
|
||||||
|
Shader = nullptr;
|
||||||
|
Textures = TArray<PPTextureInput>();
|
||||||
|
Uniforms = PPUniforms();
|
||||||
|
Viewport = PPViewport();
|
||||||
|
BlendMode = PPBlendMode();
|
||||||
|
Output = PPOutput();
|
||||||
|
ShadowMapBuffers = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetInputTexture(int index, PPTexture *texture, PPFilterMode filter = PPFilterMode::Nearest, PPWrapMode wrap = PPWrapMode::Clamp)
|
||||||
{
|
{
|
||||||
if ((int)Textures.Size() < index + 1)
|
if ((int)Textures.Size() < index + 1)
|
||||||
Textures.Resize(index + 1);
|
Textures.Resize(index + 1);
|
||||||
|
@ -117,7 +132,7 @@ public:
|
||||||
tex.Filter = filter;
|
tex.Filter = filter;
|
||||||
tex.Wrap = wrap;
|
tex.Wrap = wrap;
|
||||||
tex.Type = type;
|
tex.Type = type;
|
||||||
tex.Texture = "";
|
tex.Texture = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetShadowMapBuffers(bool enable)
|
void SetShadowMapBuffers(bool enable)
|
||||||
|
@ -125,7 +140,7 @@ public:
|
||||||
ShadowMapBuffers = enable;
|
ShadowMapBuffers = enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetOutputTexture(PPTextureName texture)
|
void SetOutputTexture(PPTexture *texture)
|
||||||
{
|
{
|
||||||
Output.Type = PPTextureType::PPTexture;
|
Output.Type = PPTextureType::PPTexture;
|
||||||
Output.Texture = texture;
|
Output.Texture = texture;
|
||||||
|
@ -134,31 +149,31 @@ public:
|
||||||
void SetOutputCurrent()
|
void SetOutputCurrent()
|
||||||
{
|
{
|
||||||
Output.Type = PPTextureType::CurrentPipelineTexture;
|
Output.Type = PPTextureType::CurrentPipelineTexture;
|
||||||
Output.Texture = "";
|
Output.Texture = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetOutputNext()
|
void SetOutputNext()
|
||||||
{
|
{
|
||||||
Output.Type = PPTextureType::NextPipelineTexture;
|
Output.Type = PPTextureType::NextPipelineTexture;
|
||||||
Output.Texture = "";
|
Output.Texture = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetOutputSceneColor()
|
void SetOutputSceneColor()
|
||||||
{
|
{
|
||||||
Output.Type = PPTextureType::SceneColor;
|
Output.Type = PPTextureType::SceneColor;
|
||||||
Output.Texture = "";
|
Output.Texture = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetOutputSwapChain()
|
void SetOutputSwapChain()
|
||||||
{
|
{
|
||||||
Output.Type = PPTextureType::SwapChain;
|
Output.Type = PPTextureType::SwapChain;
|
||||||
Output.Texture = "";
|
Output.Texture = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetOutputShadowMap()
|
void SetOutputShadowMap()
|
||||||
{
|
{
|
||||||
Output.Type = PPTextureType::ShadowMap;
|
Output.Type = PPTextureType::ShadowMap;
|
||||||
Output.Texture = "";
|
Output.Texture = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetNoBlend()
|
void SetNoBlend()
|
||||||
|
@ -185,7 +200,7 @@ public:
|
||||||
BlendMode.Flags = 0;
|
BlendMode.Flags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
PPShaderName ShaderName;
|
PPShader *Shader;
|
||||||
TArray<PPTextureInput> Textures;
|
TArray<PPTextureInput> Textures;
|
||||||
PPUniforms Uniforms;
|
PPUniforms Uniforms;
|
||||||
PPViewport Viewport;
|
PPViewport Viewport;
|
||||||
|
@ -203,65 +218,94 @@ enum class PixelFormat
|
||||||
Rgba16_snorm
|
Rgba16_snorm
|
||||||
};
|
};
|
||||||
|
|
||||||
class PPTextureDesc
|
class PPResource
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PPTextureDesc() { }
|
PPResource()
|
||||||
PPTextureDesc(int width, int height, PixelFormat format, std::shared_ptr<void> data = {}) : Width(width), Height(height), Format(format), Data(data) { }
|
{
|
||||||
|
Next = First;
|
||||||
|
First = this;
|
||||||
|
if (Next) Next->Prev = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
PPResource(const PPResource &)
|
||||||
|
{
|
||||||
|
Next = First;
|
||||||
|
First = this;
|
||||||
|
if (Next) Next->Prev = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
~PPResource()
|
||||||
|
{
|
||||||
|
if (Next) Next->Prev = Prev;
|
||||||
|
if (Prev) Prev->Next = Next;
|
||||||
|
else First = Next;
|
||||||
|
}
|
||||||
|
|
||||||
|
PPResource &operator=(const PPResource &other)
|
||||||
|
{
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ResetAll()
|
||||||
|
{
|
||||||
|
for (PPResource *cur = First; cur; cur = cur->Next)
|
||||||
|
cur->ResetBackend();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void ResetBackend() = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static PPResource *First;
|
||||||
|
PPResource *Prev = nullptr;
|
||||||
|
PPResource *Next = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PPTextureBackend
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~PPTextureBackend() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PPTexture : public PPResource
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PPTexture() = default;
|
||||||
|
PPTexture(int width, int height, PixelFormat format, std::shared_ptr<void> data = {}) : Width(width), Height(height), Format(format), Data(data) { }
|
||||||
|
|
||||||
|
void ResetBackend() override { Backend.reset(); }
|
||||||
|
|
||||||
int Width;
|
int Width;
|
||||||
int Height;
|
int Height;
|
||||||
PixelFormat Format;
|
PixelFormat Format;
|
||||||
std::shared_ptr<void> Data;
|
std::shared_ptr<void> Data;
|
||||||
|
|
||||||
|
std::unique_ptr<PPTextureBackend> Backend;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PPShader
|
class PPShaderBackend
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~PPShaderBackend() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PPShader : public PPResource
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PPShader() { }
|
PPShader() { }
|
||||||
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(); }
|
||||||
|
|
||||||
FString VertexShader = "shaders/glsl/screenquad.vp";
|
FString VertexShader = "shaders/glsl/screenquad.vp";
|
||||||
FString FragmentShader;
|
FString FragmentShader;
|
||||||
FString Defines;
|
FString Defines;
|
||||||
std::vector<UniformFieldDesc> Uniforms;
|
std::vector<UniformFieldDesc> Uniforms;
|
||||||
int Version = 330;
|
int Version = 330;
|
||||||
|
|
||||||
|
std::unique_ptr<PPShaderBackend> Backend;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PPEffectManager
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual ~PPEffectManager() { }
|
|
||||||
virtual void DeclareShaders() { }
|
|
||||||
virtual void UpdateTextures() { }
|
|
||||||
virtual void UpdateSteps() { }
|
|
||||||
};
|
|
||||||
|
|
||||||
class Postprocess
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Postprocess();
|
|
||||||
~Postprocess();
|
|
||||||
|
|
||||||
void DeclareShaders() { for (unsigned int i = 0; i < Managers.Size(); i++) Managers[i]->DeclareShaders(); }
|
|
||||||
void UpdateTextures() { for (unsigned int i = 0; i < Managers.Size(); i++) Managers[i]->UpdateTextures(); }
|
|
||||||
void UpdateSteps() { for (unsigned int i = 0; i < Managers.Size(); i++) Managers[i]->UpdateSteps(); }
|
|
||||||
|
|
||||||
int SceneWidth = 0;
|
|
||||||
int SceneHeight = 0;
|
|
||||||
int fixedcm = 0;
|
|
||||||
float gameinfobluramount = 0.0f;
|
|
||||||
float m5 = 0.0f;
|
|
||||||
|
|
||||||
TMap<FString, TArray<PPStep>> Effects;
|
|
||||||
TMap<FString, PPTextureDesc> Textures;
|
|
||||||
TMap<FString, PPShader> Shaders;
|
|
||||||
|
|
||||||
TArray<PPEffectManager*> Managers;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern Postprocess hw_postprocess;
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
struct ExtractUniforms
|
struct ExtractUniforms
|
||||||
|
@ -305,26 +349,31 @@ class PPBlurLevel
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PPViewport Viewport;
|
PPViewport Viewport;
|
||||||
PPTextureName VTexture;
|
PPTexture VTexture;
|
||||||
PPTextureName HTexture;
|
PPTexture HTexture;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PPBloom : public PPEffectManager
|
class PPBloom
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void DeclareShaders() override;
|
void RenderBloom(PPRenderState *renderstate, int sceneWidth, int sceneHeight, int fixedcm);
|
||||||
void UpdateTextures() override;
|
void RenderBlur(PPRenderState *renderstate, int sceneWidth, int sceneHeight, float gameinfobluramount);
|
||||||
void UpdateSteps() override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void UpdateBlurSteps();
|
void BlurStep(PPRenderState *renderstate, const BlurUniforms &blurUniforms, PPTexture &input, PPTexture &output, PPViewport viewport, bool vertical);
|
||||||
|
void UpdateTextures(int width, int height);
|
||||||
PPStep BlurStep(const BlurUniforms &blurUniforms, PPTextureName input, PPTextureName output, PPViewport viewport, bool vertical);
|
|
||||||
|
|
||||||
static float ComputeBlurGaussian(float n, float theta);
|
static float ComputeBlurGaussian(float n, float theta);
|
||||||
static void ComputeBlurSamples(int sampleCount, float blurAmount, float *sampleWeights);
|
static void ComputeBlurSamples(int sampleCount, float blurAmount, float *sampleWeights);
|
||||||
|
|
||||||
PPBlurLevel levels[NumBloomLevels];
|
PPBlurLevel levels[NumBloomLevels];
|
||||||
|
int lastWidth = 0;
|
||||||
|
int lastHeight = 0;
|
||||||
|
|
||||||
|
PPShader BloomCombine = { "shaders/glsl/bloomcombine.fp", "", {} };
|
||||||
|
PPShader BloomExtract = { "shaders/glsl/bloomextract.fp", "", ExtractUniforms::Desc() };
|
||||||
|
PPShader BlurVertical = { "shaders/glsl/blur.fp", "#define BLUR_VERTICAL\n", BlurUniforms::Desc() };
|
||||||
|
PPShader BlurHorizontal = { "shaders/glsl/blur.fp", "#define BLUR_HORIZONTAL\n", BlurUniforms::Desc() };
|
||||||
};
|
};
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -351,11 +400,13 @@ struct LensUniforms
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class PPLensDistort : public PPEffectManager
|
class PPLensDistort
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void DeclareShaders() override;
|
void Render(PPRenderState *renderstate);
|
||||||
void UpdateSteps() override;
|
|
||||||
|
private:
|
||||||
|
PPShader Lens = { "shaders/glsl/lensdistortion.fp", "", LensUniforms::Desc() };
|
||||||
};
|
};
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -376,15 +427,19 @@ struct FXAAUniforms
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class PPFXAA : public PPEffectManager
|
class PPFXAA
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void DeclareShaders() override;
|
void Render(PPRenderState *renderstate);
|
||||||
void UpdateSteps() override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void CreateShaders();
|
||||||
int GetMaxVersion();
|
int GetMaxVersion();
|
||||||
FString GetDefines();
|
FString GetDefines();
|
||||||
|
|
||||||
|
PPShader FXAALuma;
|
||||||
|
PPShader FXAA;
|
||||||
|
int LastQuality = -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -427,19 +482,25 @@ class PPExposureLevel
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PPViewport Viewport;
|
PPViewport Viewport;
|
||||||
PPTextureName Texture;
|
PPTexture Texture;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PPCameraExposure : public PPEffectManager
|
class PPCameraExposure
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void DeclareShaders() override;
|
void Render(PPRenderState *renderstate, int sceneWidth, int sceneHeight);
|
||||||
void UpdateTextures() override;
|
|
||||||
void UpdateSteps() override;
|
PPTexture CameraTexture = { 1, 1, PixelFormat::R32f };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TArray<PPExposureLevel> ExposureLevels;
|
void UpdateTextures(int width, int height);
|
||||||
|
|
||||||
|
std::vector<PPExposureLevel> ExposureLevels;
|
||||||
bool FirstExposureFrame = true;
|
bool FirstExposureFrame = true;
|
||||||
|
|
||||||
|
PPShader ExposureExtract = { "shaders/glsl/exposureextract.fp", "", ExposureExtractUniforms::Desc() };
|
||||||
|
PPShader ExposureAverage = { "shaders/glsl/exposureaverage.fp", "", {}, 400 };
|
||||||
|
PPShader ExposureCombine = { "shaders/glsl/exposurecombine.fp", "", ExposureCombineUniforms::Desc() };
|
||||||
};
|
};
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -459,21 +520,33 @@ struct ColormapUniforms
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class PPColormap : public PPEffectManager
|
class PPColormap
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void DeclareShaders() override;
|
void Render(PPRenderState *renderstate, int fixedcm);
|
||||||
void UpdateSteps() override;
|
|
||||||
|
private:
|
||||||
|
PPShader Colormap = { "shaders/glsl/colormap.fp", "", ColormapUniforms::Desc() };
|
||||||
};
|
};
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
class PPTonemap : public PPEffectManager
|
class PPTonemap
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void DeclareShaders() override;
|
void Render(PPRenderState *renderstate);
|
||||||
void UpdateTextures() override;
|
void ClearTonemapPalette() { PaletteTexture = {}; }
|
||||||
void UpdateSteps() override;
|
|
||||||
|
private:
|
||||||
|
void UpdateTextures();
|
||||||
|
|
||||||
|
PPTexture PaletteTexture;
|
||||||
|
|
||||||
|
PPShader LinearShader = { "shaders/glsl/tonemap.fp", "#define LINEAR\n", {} };
|
||||||
|
PPShader ReinhardShader = { "shaders/glsl/tonemap.fp", "#define REINHARD\n", {} };
|
||||||
|
PPShader HejlDawsonShader = { "shaders/glsl/tonemap.fp", "#define HEJLDAWSON\n", {} };
|
||||||
|
PPShader Uncharted2Shader = { "shaders/glsl/tonemap.fp", "#define UNCHARTED2\n", {} };
|
||||||
|
PPShader PaletteShader = { "shaders/glsl/tonemap.fp", "#define PALETTE\n", {} };
|
||||||
|
|
||||||
enum TonemapMode
|
enum TonemapMode
|
||||||
{
|
{
|
||||||
|
@ -592,14 +665,16 @@ struct AmbientCombineUniforms
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class PPAmbientOcclusion : public PPEffectManager
|
class PPAmbientOcclusion
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void DeclareShaders() override;
|
PPAmbientOcclusion();
|
||||||
void UpdateTextures() override;
|
void Render(PPRenderState *renderstate, float m5, int sceneWidth, int sceneHeight);
|
||||||
void UpdateSteps() override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void CreateShaders();
|
||||||
|
void UpdateTextures(int width, int height);
|
||||||
|
|
||||||
enum Quality
|
enum Quality
|
||||||
{
|
{
|
||||||
Off,
|
Off,
|
||||||
|
@ -612,8 +687,25 @@ private:
|
||||||
int AmbientWidth = 0;
|
int AmbientWidth = 0;
|
||||||
int AmbientHeight = 0;
|
int AmbientHeight = 0;
|
||||||
|
|
||||||
|
int LastQuality = -1;
|
||||||
|
int LastWidth = 0;
|
||||||
|
int LastHeight = 0;
|
||||||
|
|
||||||
|
PPShader LinearDepth;
|
||||||
|
PPShader LinearDepthMS;
|
||||||
|
PPShader AmbientOcclude;
|
||||||
|
PPShader AmbientOccludeMS;
|
||||||
|
PPShader BlurVertical;
|
||||||
|
PPShader BlurHorizontal;
|
||||||
|
PPShader Combine;
|
||||||
|
PPShader CombineMS;
|
||||||
|
|
||||||
|
PPTexture LinearDepthTexture;
|
||||||
|
PPTexture Ambient0;
|
||||||
|
PPTexture Ambient1;
|
||||||
|
|
||||||
enum { NumAmbientRandomTextures = 3 };
|
enum { NumAmbientRandomTextures = 3 };
|
||||||
PPTextureName AmbientRandomTexture[NumAmbientRandomTextures];
|
PPTexture AmbientRandomTexture[NumAmbientRandomTextures];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PresentUniforms
|
struct PresentUniforms
|
||||||
|
@ -646,12 +738,17 @@ struct PresentUniforms
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class PPPresent : public PPEffectManager
|
class PPPresent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void DeclareShaders() override;
|
PPPresent();
|
||||||
void UpdateTextures() override;
|
|
||||||
void UpdateSteps() override;
|
PPTexture Dither;
|
||||||
|
|
||||||
|
PPShader Present = { "shaders/glsl/present.fp", "", PresentUniforms::Desc() };
|
||||||
|
PPShader Checker3D = { "shaders/glsl/present_checker3d.fp", "", PresentUniforms::Desc() };
|
||||||
|
PPShader Column3D = { "shaders/glsl/present_column3d.fp", "", PresentUniforms::Desc() };
|
||||||
|
PPShader Row3D = { "shaders/glsl/present_row3d.fp", "", PresentUniforms::Desc() };
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ShadowMapUniforms
|
struct ShadowMapUniforms
|
||||||
|
@ -671,10 +768,29 @@ struct ShadowMapUniforms
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class PPShadowMap : public PPEffectManager
|
class PPShadowMap
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void DeclareShaders() override;
|
void Update(PPRenderState *renderstate);
|
||||||
void UpdateTextures() override;
|
|
||||||
void UpdateSteps() override;
|
private:
|
||||||
|
PPShader ShadowMap = { "shaders/glsl/shadowmap.fp", "", ShadowMapUniforms::Desc() };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class Postprocess
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PPBloom bloom;
|
||||||
|
PPLensDistort lens;
|
||||||
|
PPFXAA fxaa;
|
||||||
|
PPCameraExposure exposure;
|
||||||
|
PPColormap colormap;
|
||||||
|
PPTonemap tonemap;
|
||||||
|
PPAmbientOcclusion ssao;
|
||||||
|
PPPresent present;
|
||||||
|
PPShadowMap shadowmap;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern Postprocess hw_postprocess;
|
||||||
|
|
|
@ -40,18 +40,22 @@ void VkPostprocess::SetActiveRenderTarget()
|
||||||
void VkPostprocess::PostProcessScene(int fixedcm, const std::function<void()> &afterBloomDrawEndScene2D)
|
void VkPostprocess::PostProcessScene(int fixedcm, const std::function<void()> &afterBloomDrawEndScene2D)
|
||||||
{
|
{
|
||||||
auto fb = GetVulkanFrameBuffer();
|
auto fb = GetVulkanFrameBuffer();
|
||||||
|
int sceneWidth = fb->GetBuffers()->GetSceneWidth();
|
||||||
|
int sceneHeight = fb->GetBuffers()->GetSceneHeight();
|
||||||
|
|
||||||
hw_postprocess.fixedcm = fixedcm;
|
VkPPRenderState renderstate;
|
||||||
|
|
||||||
RenderEffect("UpdateCameraExposure");
|
hw_postprocess.exposure.Render(&renderstate, sceneWidth, sceneHeight);
|
||||||
//mCustomPostProcessShaders->Run("beforebloom");
|
//mCustomPostProcessShaders->Run("beforebloom");
|
||||||
RenderEffect("BloomScene");
|
hw_postprocess.bloom.RenderBloom(&renderstate, sceneWidth, sceneHeight, fixedcm);
|
||||||
|
|
||||||
SetActiveRenderTarget();
|
SetActiveRenderTarget();
|
||||||
afterBloomDrawEndScene2D();
|
afterBloomDrawEndScene2D();
|
||||||
RenderEffect("TonemapScene");
|
|
||||||
RenderEffect("ColormapScene");
|
hw_postprocess.tonemap.Render(&renderstate);
|
||||||
RenderEffect("LensDistortScene");
|
hw_postprocess.colormap.Render(&renderstate, fixedcm);
|
||||||
RenderEffect("ApplyFXAA");
|
hw_postprocess.lens.Render(&renderstate);
|
||||||
|
hw_postprocess.fxaa.Render(&renderstate);
|
||||||
//mCustomPostProcessShaders->Run("scene");
|
//mCustomPostProcessShaders->Run("scene");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,53 +187,56 @@ void VkPostprocess::DrawPresentTexture(const IntRect &box, bool applyGamma, bool
|
||||||
uniforms.Scale = { screen->mScreenViewport.width / (float)fb->GetBuffers()->GetWidth(), -screen->mScreenViewport.height / (float)fb->GetBuffers()->GetHeight() };
|
uniforms.Scale = { screen->mScreenViewport.width / (float)fb->GetBuffers()->GetWidth(), -screen->mScreenViewport.height / (float)fb->GetBuffers()->GetHeight() };
|
||||||
uniforms.Offset = { 0.0f, 1.0f };
|
uniforms.Offset = { 0.0f, 1.0f };
|
||||||
|
|
||||||
PPStep step;
|
VkPPRenderState renderstate;
|
||||||
step.ShaderName = "Present";
|
renderstate.Shader = &hw_postprocess.present.Present;
|
||||||
step.Uniforms.Set(uniforms);
|
renderstate.Uniforms.Set(uniforms);
|
||||||
step.Viewport = box;
|
renderstate.Viewport = box;
|
||||||
step.SetInputCurrent(0, ViewportLinearScale() ? PPFilterMode::Linear : PPFilterMode::Nearest);
|
renderstate.SetInputCurrent(0, ViewportLinearScale() ? PPFilterMode::Linear : PPFilterMode::Nearest);
|
||||||
step.SetInputTexture(1, "PresentDither", PPFilterMode::Nearest, PPWrapMode::Repeat);
|
renderstate.SetInputTexture(1, &hw_postprocess.present.Dither, PPFilterMode::Nearest, PPWrapMode::Repeat);
|
||||||
step.SetOutputSwapChain();
|
renderstate.SetOutputSwapChain();
|
||||||
step.SetNoBlend();
|
renderstate.SetNoBlend();
|
||||||
//if (clearBorders) step.SetClearBorders();
|
//if (clearBorders) renderstate.SetClearBorders();
|
||||||
|
renderstate.Draw();
|
||||||
TArray<PPStep> steps;
|
|
||||||
steps.Push(step);
|
|
||||||
hw_postprocess.Effects["Present"] = steps;
|
|
||||||
|
|
||||||
RenderEffect("Present");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VkPostprocess::AmbientOccludeScene(float m5)
|
void VkPostprocess::AmbientOccludeScene(float m5)
|
||||||
{
|
{
|
||||||
hw_postprocess.m5 = m5;
|
auto fb = GetVulkanFrameBuffer();
|
||||||
|
int sceneWidth = fb->GetBuffers()->GetSceneWidth();
|
||||||
|
int sceneHeight = fb->GetBuffers()->GetSceneHeight();
|
||||||
|
|
||||||
RenderEffect("AmbientOccludeScene");
|
VkPPRenderState renderstate;
|
||||||
|
hw_postprocess.ssao.Render(&renderstate, m5, sceneWidth, sceneHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VkPostprocess::BlurScene(float gameinfobluramount)
|
void VkPostprocess::BlurScene(float gameinfobluramount)
|
||||||
{
|
{
|
||||||
hw_postprocess.gameinfobluramount = gameinfobluramount;
|
auto fb = GetVulkanFrameBuffer();
|
||||||
|
int sceneWidth = fb->GetBuffers()->GetSceneWidth();
|
||||||
|
int sceneHeight = fb->GetBuffers()->GetSceneHeight();
|
||||||
|
|
||||||
|
VkPPRenderState renderstate;
|
||||||
|
|
||||||
auto vrmode = VRMode::GetVRMode(true);
|
auto vrmode = VRMode::GetVRMode(true);
|
||||||
int eyeCount = vrmode->mEyeCount;
|
int eyeCount = vrmode->mEyeCount;
|
||||||
for (int i = 0; i < eyeCount; ++i)
|
for (int i = 0; i < eyeCount; ++i)
|
||||||
{
|
{
|
||||||
RenderEffect("BlurScene");
|
hw_postprocess.bloom.RenderBlur(&renderstate, sceneWidth, sceneHeight, gameinfobluramount);
|
||||||
if (eyeCount - i > 1) NextEye(eyeCount);
|
if (eyeCount - i > 1) NextEye(eyeCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VkPostprocess::ClearTonemapPalette()
|
void VkPostprocess::ClearTonemapPalette()
|
||||||
{
|
{
|
||||||
hw_postprocess.Textures.Remove("Tonemap.Palette");
|
hw_postprocess.tonemap.ClearTonemapPalette();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VkPostprocess::UpdateShadowMap()
|
void VkPostprocess::UpdateShadowMap()
|
||||||
{
|
{
|
||||||
if (screen->mShadowMap.PerformUpdate())
|
if (screen->mShadowMap.PerformUpdate())
|
||||||
{
|
{
|
||||||
RenderEffect("UpdateShadowMap");
|
VkPPRenderState renderstate;
|
||||||
|
hw_postprocess.shadowmap.Update(&renderstate);
|
||||||
|
|
||||||
auto fb = GetVulkanFrameBuffer();
|
auto fb = GetVulkanFrameBuffer();
|
||||||
auto buffers = fb->GetBuffers();
|
auto buffers = fb->GetBuffers();
|
||||||
|
@ -255,17 +262,6 @@ void VkPostprocess::BeginFrame()
|
||||||
mDescriptorPool = builder.create(GetVulkanFrameBuffer()->device);
|
mDescriptorPool = builder.create(GetVulkanFrameBuffer()->device);
|
||||||
mDescriptorPool->SetDebugName("VkPostprocess.mDescriptorPool");
|
mDescriptorPool->SetDebugName("VkPostprocess.mDescriptorPool");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto fb = GetVulkanFrameBuffer();
|
|
||||||
hw_postprocess.SceneWidth = fb->GetBuffers()->GetSceneWidth();
|
|
||||||
hw_postprocess.SceneHeight = fb->GetBuffers()->GetSceneHeight();
|
|
||||||
|
|
||||||
hw_postprocess.DeclareShaders();
|
|
||||||
hw_postprocess.UpdateTextures();
|
|
||||||
hw_postprocess.UpdateSteps();
|
|
||||||
|
|
||||||
CompileEffectShaders();
|
|
||||||
UpdateEffectTextures();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VkPostprocess::RenderBuffersReset()
|
void VkPostprocess::RenderBuffersReset()
|
||||||
|
@ -273,128 +269,125 @@ void VkPostprocess::RenderBuffersReset()
|
||||||
mRenderPassSetup.clear();
|
mRenderPassSetup.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VkPostprocess::UpdateEffectTextures()
|
VulkanSampler *VkPostprocess::GetSampler(PPFilterMode filter, PPWrapMode wrap)
|
||||||
|
{
|
||||||
|
int index = (((int)filter) << 2) | (int)wrap;
|
||||||
|
auto &sampler = mSamplers[index];
|
||||||
|
if (sampler)
|
||||||
|
return sampler.get();
|
||||||
|
|
||||||
|
SamplerBuilder builder;
|
||||||
|
builder.setMipmapMode(VK_SAMPLER_MIPMAP_MODE_NEAREST);
|
||||||
|
builder.setMinFilter(filter == PPFilterMode::Nearest ? VK_FILTER_NEAREST : VK_FILTER_LINEAR);
|
||||||
|
builder.setMagFilter(filter == PPFilterMode::Nearest ? VK_FILTER_NEAREST : VK_FILTER_LINEAR);
|
||||||
|
builder.setAddressMode(wrap == PPWrapMode::Clamp ? VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE : VK_SAMPLER_ADDRESS_MODE_REPEAT);
|
||||||
|
sampler = builder.create(GetVulkanFrameBuffer()->device);
|
||||||
|
sampler->SetDebugName("VkPostprocess.mSamplers");
|
||||||
|
return sampler.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VkPostprocess::NextEye(int eyeCount)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
VkPPTexture::VkPPTexture(PPTexture *texture)
|
||||||
{
|
{
|
||||||
auto fb = GetVulkanFrameBuffer();
|
auto fb = GetVulkanFrameBuffer();
|
||||||
|
|
||||||
TMap<FString, PPTextureDesc>::Iterator it(hw_postprocess.Textures);
|
VkFormat format;
|
||||||
TMap<FString, PPTextureDesc>::Pair *pair;
|
int pixelsize;
|
||||||
while (it.NextPair(pair))
|
switch (texture->Format)
|
||||||
{
|
{
|
||||||
const auto &desc = pair->Value;
|
default:
|
||||||
auto &vktex = mTextures[pair->Key];
|
case PixelFormat::Rgba8: format = VK_FORMAT_R8G8B8A8_UNORM; pixelsize = 4; break;
|
||||||
|
case PixelFormat::Rgba16f: format = VK_FORMAT_R16G16B16A16_SFLOAT; pixelsize = 8; break;
|
||||||
|
case PixelFormat::R32f: format = VK_FORMAT_R32_SFLOAT; pixelsize = 4; break;
|
||||||
|
case PixelFormat::Rg16f: format = VK_FORMAT_R16G16_SFLOAT; pixelsize = 4; break;
|
||||||
|
case PixelFormat::Rgba16_snorm: format = VK_FORMAT_R16G16B16A16_SNORM; pixelsize = 8; break;
|
||||||
|
}
|
||||||
|
|
||||||
if (vktex && (vktex->Image->width != desc.Width || vktex->Image->height != desc.Height))
|
ImageBuilder imgbuilder;
|
||||||
vktex.reset();
|
imgbuilder.setFormat(format);
|
||||||
|
imgbuilder.setSize(texture->Width, texture->Height);
|
||||||
|
if (texture->Data)
|
||||||
|
imgbuilder.setUsage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
|
||||||
|
else
|
||||||
|
imgbuilder.setUsage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
|
||||||
|
if (!imgbuilder.isFormatSupported(fb->device))
|
||||||
|
I_FatalError("Vulkan device does not support the image format required by a postprocess texture\n");
|
||||||
|
Image = imgbuilder.create(fb->device);
|
||||||
|
Image->SetDebugName("VkPPTexture");
|
||||||
|
Format = format;
|
||||||
|
|
||||||
if (!vktex)
|
ImageViewBuilder viewbuilder;
|
||||||
{
|
viewbuilder.setImage(Image.get(), format);
|
||||||
vktex.reset(new VkPPTexture());
|
View = viewbuilder.create(fb->device);
|
||||||
|
View->SetDebugName("VkPPTextureView");
|
||||||
|
|
||||||
VkFormat format;
|
if (texture->Data)
|
||||||
int pixelsize;
|
{
|
||||||
switch (pair->Value.Format)
|
size_t totalsize = texture->Width * texture->Height * pixelsize;
|
||||||
{
|
BufferBuilder stagingbuilder;
|
||||||
default:
|
stagingbuilder.setSize(totalsize);
|
||||||
case PixelFormat::Rgba8: format = VK_FORMAT_R8G8B8A8_UNORM; pixelsize = 4; break;
|
stagingbuilder.setUsage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY);
|
||||||
case PixelFormat::Rgba16f: format = VK_FORMAT_R16G16B16A16_SFLOAT; pixelsize = 8; break;
|
Staging = stagingbuilder.create(fb->device);
|
||||||
case PixelFormat::R32f: format = VK_FORMAT_R32_SFLOAT; pixelsize = 4; break;
|
Staging->SetDebugName("VkPPTextureStaging");
|
||||||
case PixelFormat::Rg16f: format = VK_FORMAT_R16G16_SFLOAT; pixelsize = 4; break;
|
|
||||||
case PixelFormat::Rgba16_snorm: format = VK_FORMAT_R16G16B16A16_SNORM; pixelsize = 8; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
ImageBuilder imgbuilder;
|
PipelineBarrier barrier0;
|
||||||
imgbuilder.setFormat(format);
|
barrier0.addImage(Image.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, VK_ACCESS_TRANSFER_WRITE_BIT);
|
||||||
imgbuilder.setSize(desc.Width, desc.Height);
|
barrier0.execute(fb->GetUploadCommands(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
|
||||||
if (desc.Data)
|
|
||||||
imgbuilder.setUsage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
|
|
||||||
else
|
|
||||||
imgbuilder.setUsage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
|
|
||||||
if (!imgbuilder.isFormatSupported(fb->device))
|
|
||||||
I_FatalError("Vulkan device does not support the image format required by %s\n", pair->Key.GetChars());
|
|
||||||
vktex->Image = imgbuilder.create(fb->device);
|
|
||||||
vktex->Image->SetDebugName(pair->Key.GetChars());
|
|
||||||
vktex->Format = format;
|
|
||||||
|
|
||||||
ImageViewBuilder viewbuilder;
|
void *data = Staging->Map(0, totalsize);
|
||||||
viewbuilder.setImage(vktex->Image.get(), format);
|
memcpy(data, texture->Data.get(), totalsize);
|
||||||
vktex->View = viewbuilder.create(fb->device);
|
Staging->Unmap();
|
||||||
vktex->View->SetDebugName(pair->Key.GetChars());
|
|
||||||
|
|
||||||
if (desc.Data)
|
VkBufferImageCopy region = {};
|
||||||
{
|
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
size_t totalsize = desc.Width * desc.Height * pixelsize;
|
region.imageSubresource.layerCount = 1;
|
||||||
BufferBuilder stagingbuilder;
|
region.imageExtent.depth = 1;
|
||||||
stagingbuilder.setSize(totalsize);
|
region.imageExtent.width = texture->Width;
|
||||||
stagingbuilder.setUsage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY);
|
region.imageExtent.height = texture->Height;
|
||||||
vktex->Staging = stagingbuilder.create(fb->device);
|
fb->GetUploadCommands()->copyBufferToImage(Staging->buffer, Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
||||||
vktex->Staging->SetDebugName(pair->Key.GetChars());
|
|
||||||
|
|
||||||
PipelineBarrier barrier0;
|
PipelineBarrier barrier1;
|
||||||
barrier0.addImage(vktex->Image.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, VK_ACCESS_TRANSFER_WRITE_BIT);
|
barrier1.addImage(Image.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT);
|
||||||
barrier0.execute(fb->GetUploadCommands(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
|
barrier1.execute(fb->GetUploadCommands(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||||
|
Layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||||
void *data = vktex->Staging->Map(0, totalsize);
|
}
|
||||||
memcpy(data, desc.Data.get(), totalsize);
|
else
|
||||||
vktex->Staging->Unmap();
|
{
|
||||||
|
PipelineBarrier barrier;
|
||||||
VkBufferImageCopy region = {};
|
barrier.addImage(Image.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT);
|
||||||
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
barrier.execute(fb->GetUploadCommands(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
|
||||||
region.imageSubresource.layerCount = 1;
|
Layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||||
region.imageExtent.depth = 1;
|
|
||||||
region.imageExtent.width = desc.Width;
|
|
||||||
region.imageExtent.height = desc.Height;
|
|
||||||
fb->GetUploadCommands()->copyBufferToImage(vktex->Staging->buffer, vktex->Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
|
||||||
|
|
||||||
PipelineBarrier barrier1;
|
|
||||||
barrier1.addImage(vktex->Image.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT);
|
|
||||||
barrier1.execute(fb->GetUploadCommands(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
|
||||||
vktex->Layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PipelineBarrier barrier;
|
|
||||||
barrier.addImage(vktex->Image.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT);
|
|
||||||
barrier.execute(fb->GetUploadCommands(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
|
|
||||||
vktex->Layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VkPostprocess::CompileEffectShaders()
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
VkPPShader::VkPPShader(PPShader *shader)
|
||||||
{
|
{
|
||||||
auto fb = GetVulkanFrameBuffer();
|
auto fb = GetVulkanFrameBuffer();
|
||||||
|
|
||||||
TMap<FString, PPShader>::Iterator it(hw_postprocess.Shaders);
|
FString prolog;
|
||||||
TMap<FString, PPShader>::Pair *pair;
|
if (!shader->Uniforms.empty())
|
||||||
while (it.NextPair(pair))
|
prolog = UniformBlockDecl::Create("Uniforms", shader->Uniforms, -1);
|
||||||
{
|
prolog += shader->Defines;
|
||||||
const auto &desc = pair->Value;
|
|
||||||
auto &vkshader = mShaders[pair->Key];
|
|
||||||
if (!vkshader)
|
|
||||||
{
|
|
||||||
vkshader.reset(new VkPPShader());
|
|
||||||
|
|
||||||
FString prolog;
|
ShaderBuilder vertbuilder;
|
||||||
if (!desc.Uniforms.empty())
|
vertbuilder.setVertexShader(LoadShaderCode(shader->VertexShader, "", shader->Version));
|
||||||
prolog = UniformBlockDecl::Create("Uniforms", desc.Uniforms, -1);
|
VertexShader = vertbuilder.create(fb->device);
|
||||||
prolog += desc.Defines;
|
VertexShader->SetDebugName(shader->VertexShader.GetChars());
|
||||||
|
|
||||||
ShaderBuilder vertbuilder;
|
ShaderBuilder fragbuilder;
|
||||||
vertbuilder.setVertexShader(LoadShaderCode(desc.VertexShader, "", desc.Version));
|
fragbuilder.setFragmentShader(LoadShaderCode(shader->FragmentShader, prolog, shader->Version));
|
||||||
vkshader->VertexShader = vertbuilder.create(fb->device);
|
FragmentShader = fragbuilder.create(fb->device);
|
||||||
vkshader->VertexShader->SetDebugName(desc.VertexShader.GetChars());
|
FragmentShader->SetDebugName(shader->FragmentShader.GetChars());
|
||||||
|
|
||||||
ShaderBuilder fragbuilder;
|
|
||||||
fragbuilder.setFragmentShader(LoadShaderCode(desc.FragmentShader, prolog, desc.Version));
|
|
||||||
vkshader->FragmentShader = fragbuilder.create(fb->device);
|
|
||||||
vkshader->FragmentShader->SetDebugName(desc.FragmentShader.GetChars());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FString VkPostprocess::LoadShaderCode(const FString &lumpName, const FString &defines, int version)
|
FString VkPPShader::LoadShaderCode(const FString &lumpName, const FString &defines, int version)
|
||||||
{
|
{
|
||||||
int lump = Wads.CheckNumForFullName(lumpName);
|
int lump = Wads.CheckNumForFullName(lumpName);
|
||||||
if (lump == -1) I_FatalError("Unable to load '%s'", lumpName.GetChars());
|
if (lump == -1) I_FatalError("Unable to load '%s'", lumpName.GetChars());
|
||||||
|
@ -408,50 +401,49 @@ FString VkPostprocess::LoadShaderCode(const FString &lumpName, const FString &de
|
||||||
return patchedCode;
|
return patchedCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VkPostprocess::RenderEffect(const FString &name)
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void VkPPRenderState::Draw()
|
||||||
{
|
{
|
||||||
GetVulkanFrameBuffer()->GetRenderState()->EndRenderPass();
|
auto fb = GetVulkanFrameBuffer();
|
||||||
|
auto pp = fb->GetPostprocess();
|
||||||
|
|
||||||
if (hw_postprocess.Effects[name].Size() == 0)
|
fb->GetRenderState()->EndRenderPass();
|
||||||
return;
|
|
||||||
|
|
||||||
for (const PPStep &step : hw_postprocess.Effects[name])
|
VkPPRenderPassKey key;
|
||||||
|
key.BlendMode = BlendMode;
|
||||||
|
key.InputTextures = Textures.Size();
|
||||||
|
key.Uniforms = Uniforms.Data.Size();
|
||||||
|
key.Shader = GetVkShader(Shader);
|
||||||
|
key.SwapChain = (Output.Type == PPTextureType::SwapChain);
|
||||||
|
key.ShadowMapBuffers = ShadowMapBuffers;
|
||||||
|
if (Output.Type == PPTextureType::PPTexture)
|
||||||
|
key.OutputFormat = GetVkTexture(Output.Texture)->Format;
|
||||||
|
else if (Output.Type == PPTextureType::SwapChain)
|
||||||
|
key.OutputFormat = GetVulkanFrameBuffer()->swapChain->swapChainFormat.format;
|
||||||
|
else if (Output.Type == PPTextureType::ShadowMap)
|
||||||
|
key.OutputFormat = VK_FORMAT_R32_SFLOAT;
|
||||||
|
else
|
||||||
|
key.OutputFormat = VK_FORMAT_R16G16B16A16_SFLOAT;
|
||||||
|
|
||||||
|
auto &passSetup = pp->mRenderPassSetup[key];
|
||||||
|
if (!passSetup)
|
||||||
|
passSetup.reset(new VkPPRenderPassSetup(key));
|
||||||
|
|
||||||
|
int framebufferWidth = 0, framebufferHeight = 0;
|
||||||
|
VulkanDescriptorSet *input = GetInput(passSetup.get(), Textures, ShadowMapBuffers);
|
||||||
|
VulkanFramebuffer *output = GetOutput(passSetup.get(), Output, framebufferWidth, framebufferHeight);
|
||||||
|
|
||||||
|
RenderScreenQuad(passSetup.get(), input, output, framebufferWidth, framebufferHeight, Viewport.left, Viewport.top, Viewport.width, Viewport.height, Uniforms.Data.Data(), Uniforms.Data.Size());
|
||||||
|
|
||||||
|
// Advance to next PP texture if our output was sent there
|
||||||
|
if (Output.Type == PPTextureType::NextPipelineTexture)
|
||||||
{
|
{
|
||||||
VkPPRenderPassKey key;
|
pp->mCurrentPipelineImage = (pp->mCurrentPipelineImage + 1) % VkRenderBuffers::NumPipelineImages;
|
||||||
key.BlendMode = step.BlendMode;
|
|
||||||
key.InputTextures = step.Textures.Size();
|
|
||||||
key.Uniforms = step.Uniforms.Data.Size();
|
|
||||||
key.Shader = mShaders[step.ShaderName].get();
|
|
||||||
key.SwapChain = (step.Output.Type == PPTextureType::SwapChain);
|
|
||||||
key.ShadowMapBuffers = step.ShadowMapBuffers;
|
|
||||||
if (step.Output.Type == PPTextureType::PPTexture)
|
|
||||||
key.OutputFormat = mTextures[step.Output.Texture]->Format;
|
|
||||||
else if (step.Output.Type == PPTextureType::SwapChain)
|
|
||||||
key.OutputFormat = GetVulkanFrameBuffer()->swapChain->swapChainFormat.format;
|
|
||||||
else if (step.Output.Type == PPTextureType::ShadowMap)
|
|
||||||
key.OutputFormat = VK_FORMAT_R32_SFLOAT;
|
|
||||||
else
|
|
||||||
key.OutputFormat = VK_FORMAT_R16G16B16A16_SFLOAT;
|
|
||||||
|
|
||||||
auto &passSetup = mRenderPassSetup[key];
|
|
||||||
if (!passSetup)
|
|
||||||
passSetup.reset(new VkPPRenderPassSetup(key));
|
|
||||||
|
|
||||||
int framebufferWidth = 0, framebufferHeight = 0;
|
|
||||||
VulkanDescriptorSet *input = GetInput(passSetup.get(), step.Textures, step.ShadowMapBuffers);
|
|
||||||
VulkanFramebuffer *output = GetOutput(passSetup.get(), step.Output, framebufferWidth, framebufferHeight);
|
|
||||||
|
|
||||||
RenderScreenQuad(passSetup.get(), input, output, framebufferWidth, framebufferHeight, step.Viewport.left, step.Viewport.top, step.Viewport.width, step.Viewport.height, step.Uniforms.Data.Data(), step.Uniforms.Data.Size());
|
|
||||||
|
|
||||||
// Advance to next PP texture if our output was sent there
|
|
||||||
if (step.Output.Type == PPTextureType::NextPipelineTexture)
|
|
||||||
{
|
|
||||||
mCurrentPipelineImage = (mCurrentPipelineImage + 1) % VkRenderBuffers::NumPipelineImages;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VkPostprocess::RenderScreenQuad(VkPPRenderPassSetup *passSetup, VulkanDescriptorSet *descriptorSet, VulkanFramebuffer *framebuffer, int framebufferWidth, int framebufferHeight, int x, int y, int width, int height, const void *pushConstants, uint32_t pushConstantsSize)
|
void VkPPRenderState::RenderScreenQuad(VkPPRenderPassSetup *passSetup, VulkanDescriptorSet *descriptorSet, VulkanFramebuffer *framebuffer, int framebufferWidth, int framebufferHeight, int x, int y, int width, int height, const void *pushConstants, uint32_t pushConstantsSize)
|
||||||
{
|
{
|
||||||
auto fb = GetVulkanFrameBuffer();
|
auto fb = GetVulkanFrameBuffer();
|
||||||
auto cmdbuffer = fb->GetDrawCommands();
|
auto cmdbuffer = fb->GetDrawCommands();
|
||||||
|
@ -491,10 +483,11 @@ void VkPostprocess::RenderScreenQuad(VkPPRenderPassSetup *passSetup, VulkanDescr
|
||||||
cmdbuffer->endRenderPass();
|
cmdbuffer->endRenderPass();
|
||||||
}
|
}
|
||||||
|
|
||||||
VulkanDescriptorSet *VkPostprocess::GetInput(VkPPRenderPassSetup *passSetup, const TArray<PPTextureInput> &textures, bool bindShadowMapBuffers)
|
VulkanDescriptorSet *VkPPRenderState::GetInput(VkPPRenderPassSetup *passSetup, const TArray<PPTextureInput> &textures, bool bindShadowMapBuffers)
|
||||||
{
|
{
|
||||||
auto fb = GetVulkanFrameBuffer();
|
auto fb = GetVulkanFrameBuffer();
|
||||||
auto descriptors = mDescriptorPool->allocate(passSetup->DescriptorLayout.get());
|
auto pp = fb->GetPostprocess();
|
||||||
|
auto descriptors = pp->mDescriptorPool->allocate(passSetup->DescriptorLayout.get());
|
||||||
descriptors->SetDebugName("VkPostprocess.descriptors");
|
descriptors->SetDebugName("VkPostprocess.descriptors");
|
||||||
|
|
||||||
WriteDescriptors write;
|
WriteDescriptors write;
|
||||||
|
@ -503,7 +496,7 @@ VulkanDescriptorSet *VkPostprocess::GetInput(VkPPRenderPassSetup *passSetup, con
|
||||||
for (unsigned int index = 0; index < textures.Size(); index++)
|
for (unsigned int index = 0; index < textures.Size(); index++)
|
||||||
{
|
{
|
||||||
const PPTextureInput &input = textures[index];
|
const PPTextureInput &input = textures[index];
|
||||||
VulkanSampler *sampler = GetSampler(input.Filter, input.Wrap);
|
VulkanSampler *sampler = pp->GetSampler(input.Filter, input.Wrap);
|
||||||
TextureImage tex = GetTexture(input.Type, input.Texture);
|
TextureImage tex = GetTexture(input.Type, input.Texture);
|
||||||
|
|
||||||
write.addCombinedImageSampler(descriptors.get(), index, tex.view, sampler, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
write.addCombinedImageSampler(descriptors.get(), index, tex.view, sampler, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||||
|
@ -520,11 +513,11 @@ VulkanDescriptorSet *VkPostprocess::GetInput(VkPPRenderPassSetup *passSetup, con
|
||||||
write.updateSets(fb->device);
|
write.updateSets(fb->device);
|
||||||
imageTransition.execute(fb->GetDrawCommands());
|
imageTransition.execute(fb->GetDrawCommands());
|
||||||
|
|
||||||
mFrameDescriptorSets.push_back(std::move(descriptors));
|
pp->mFrameDescriptorSets.push_back(std::move(descriptors));
|
||||||
return mFrameDescriptorSets.back().get();
|
return pp->mFrameDescriptorSets.back().get();
|
||||||
}
|
}
|
||||||
|
|
||||||
VulkanFramebuffer *VkPostprocess::GetOutput(VkPPRenderPassSetup *passSetup, const PPOutput &output, int &framebufferWidth, int &framebufferHeight)
|
VulkanFramebuffer *VkPPRenderState::GetOutput(VkPPRenderPassSetup *passSetup, const PPOutput &output, int &framebufferWidth, int &framebufferHeight)
|
||||||
{
|
{
|
||||||
auto fb = GetVulkanFrameBuffer();
|
auto fb = GetVulkanFrameBuffer();
|
||||||
|
|
||||||
|
@ -565,14 +558,14 @@ VulkanFramebuffer *VkPostprocess::GetOutput(VkPPRenderPassSetup *passSetup, cons
|
||||||
return framebuffer.get();
|
return framebuffer.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
VkPostprocess::TextureImage VkPostprocess::GetTexture(const PPTextureType &type, const PPTextureName &name)
|
VkPPRenderState::TextureImage VkPPRenderState::GetTexture(const PPTextureType &type, PPTexture *pptexture)
|
||||||
{
|
{
|
||||||
auto fb = GetVulkanFrameBuffer();
|
auto fb = GetVulkanFrameBuffer();
|
||||||
TextureImage tex = {};
|
TextureImage tex = {};
|
||||||
|
|
||||||
if (type == PPTextureType::CurrentPipelineTexture || type == PPTextureType::NextPipelineTexture)
|
if (type == PPTextureType::CurrentPipelineTexture || type == PPTextureType::NextPipelineTexture)
|
||||||
{
|
{
|
||||||
int idx = mCurrentPipelineImage;
|
int idx = fb->GetPostprocess()->mCurrentPipelineImage;
|
||||||
if (type == PPTextureType::NextPipelineTexture)
|
if (type == PPTextureType::NextPipelineTexture)
|
||||||
idx = (idx + 1) % VkRenderBuffers::NumPipelineImages;
|
idx = (idx + 1) % VkRenderBuffers::NumPipelineImages;
|
||||||
|
|
||||||
|
@ -583,10 +576,11 @@ VkPostprocess::TextureImage VkPostprocess::GetTexture(const PPTextureType &type,
|
||||||
}
|
}
|
||||||
else if (type == PPTextureType::PPTexture)
|
else if (type == PPTextureType::PPTexture)
|
||||||
{
|
{
|
||||||
tex.image = mTextures[name]->Image.get();
|
auto vktex = GetVkTexture(pptexture);
|
||||||
tex.view = mTextures[name]->View.get();
|
tex.image = vktex->Image.get();
|
||||||
tex.layout = &mTextures[name]->Layout;
|
tex.view = vktex->View.get();
|
||||||
tex.debugname = name.GetChars();
|
tex.layout = &vktex->Layout;
|
||||||
|
tex.debugname = "PPTexture";
|
||||||
}
|
}
|
||||||
else if (type == PPTextureType::SceneColor)
|
else if (type == PPTextureType::SceneColor)
|
||||||
{
|
{
|
||||||
|
@ -632,31 +626,24 @@ VkPostprocess::TextureImage VkPostprocess::GetTexture(const PPTextureType &type,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
I_FatalError("VkPostprocess::GetTexture not implemented yet for this texture type");
|
I_FatalError("VkPPRenderState::GetTexture not implemented yet for this texture type");
|
||||||
}
|
}
|
||||||
|
|
||||||
return tex;
|
return tex;
|
||||||
}
|
}
|
||||||
|
|
||||||
VulkanSampler *VkPostprocess::GetSampler(PPFilterMode filter, PPWrapMode wrap)
|
VkPPShader *VkPPRenderState::GetVkShader(PPShader *shader)
|
||||||
{
|
{
|
||||||
int index = (((int)filter) << 2) | (int)wrap;
|
if (!shader->Backend)
|
||||||
auto &sampler = mSamplers[index];
|
shader->Backend = std::make_unique<VkPPShader>(shader);
|
||||||
if (sampler)
|
return static_cast<VkPPShader*>(shader->Backend.get());
|
||||||
return sampler.get();
|
|
||||||
|
|
||||||
SamplerBuilder builder;
|
|
||||||
builder.setMipmapMode(VK_SAMPLER_MIPMAP_MODE_NEAREST);
|
|
||||||
builder.setMinFilter(filter == PPFilterMode::Nearest ? VK_FILTER_NEAREST : VK_FILTER_LINEAR);
|
|
||||||
builder.setMagFilter(filter == PPFilterMode::Nearest ? VK_FILTER_NEAREST : VK_FILTER_LINEAR);
|
|
||||||
builder.setAddressMode(wrap == PPWrapMode::Clamp ? VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE : VK_SAMPLER_ADDRESS_MODE_REPEAT);
|
|
||||||
sampler = builder.create(GetVulkanFrameBuffer()->device);
|
|
||||||
sampler->SetDebugName("VkPostprocess.mSamplers");
|
|
||||||
return sampler.get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VkPostprocess::NextEye(int eyeCount)
|
VkPPTexture *VkPPRenderState::GetVkTexture(PPTexture *texture)
|
||||||
{
|
{
|
||||||
|
if (!texture->Backend)
|
||||||
|
texture->Backend = std::make_unique<VkPPTexture>(texture);
|
||||||
|
return static_cast<VkPPTexture*>(texture->Backend.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -68,45 +68,36 @@ public:
|
||||||
void DrawPresentTexture(const IntRect &box, bool applyGamma, bool clearBorders);
|
void DrawPresentTexture(const IntRect &box, bool applyGamma, bool clearBorders);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void UpdateEffectTextures();
|
|
||||||
void CompileEffectShaders();
|
|
||||||
FString LoadShaderCode(const FString &lumpname, const FString &defines, int version);
|
|
||||||
void RenderEffect(const FString &name);
|
|
||||||
void NextEye(int eyeCount);
|
void NextEye(int eyeCount);
|
||||||
void RenderScreenQuad(VkPPRenderPassSetup *passSetup, VulkanDescriptorSet *descriptorSet, VulkanFramebuffer *framebuffer, int framebufferWidth, int framebufferHeight, int x, int y, int width, int height, const void *pushConstants, uint32_t pushConstantsSize);
|
|
||||||
|
|
||||||
VulkanDescriptorSet *GetInput(VkPPRenderPassSetup *passSetup, const TArray<PPTextureInput> &textures, bool bindShadowMapBuffers);
|
|
||||||
VulkanFramebuffer *GetOutput(VkPPRenderPassSetup *passSetup, const PPOutput &output, int &framebufferWidth, int &framebufferHeight);
|
|
||||||
VulkanSampler *GetSampler(PPFilterMode filter, PPWrapMode wrap);
|
VulkanSampler *GetSampler(PPFilterMode filter, PPWrapMode wrap);
|
||||||
|
|
||||||
struct TextureImage
|
|
||||||
{
|
|
||||||
VulkanImage *image;
|
|
||||||
VulkanImageView *view;
|
|
||||||
VkImageLayout *layout;
|
|
||||||
const char *debugname;
|
|
||||||
};
|
|
||||||
TextureImage GetTexture(const PPTextureType &type, const PPTextureName &name);
|
|
||||||
|
|
||||||
std::map<PPTextureName, std::unique_ptr<VkPPTexture>> mTextures;
|
|
||||||
std::map<PPShaderName, std::unique_ptr<VkPPShader>> mShaders;
|
|
||||||
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;
|
std::vector<std::unique_ptr<VulkanDescriptorSet>> mFrameDescriptorSets;
|
||||||
int mCurrentPipelineImage = 0;
|
int mCurrentPipelineImage = 0;
|
||||||
|
|
||||||
|
friend class VkPPRenderState;
|
||||||
};
|
};
|
||||||
|
|
||||||
class VkPPShader
|
class VkPPShader : public PPShaderBackend
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
VkPPShader(PPShader *shader);
|
||||||
|
|
||||||
std::unique_ptr<VulkanShader> VertexShader;
|
std::unique_ptr<VulkanShader> VertexShader;
|
||||||
std::unique_ptr<VulkanShader> FragmentShader;
|
std::unique_ptr<VulkanShader> FragmentShader;
|
||||||
|
|
||||||
|
private:
|
||||||
|
FString LoadShaderCode(const FString &lumpname, const FString &defines, int version);
|
||||||
};
|
};
|
||||||
|
|
||||||
class VkPPTexture
|
class VkPPTexture : public PPTextureBackend
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
VkPPTexture(PPTexture *texture);
|
||||||
|
|
||||||
std::unique_ptr<VulkanImage> Image;
|
std::unique_ptr<VulkanImage> Image;
|
||||||
std::unique_ptr<VulkanImageView> View;
|
std::unique_ptr<VulkanImageView> View;
|
||||||
std::unique_ptr<VulkanBuffer> Staging;
|
std::unique_ptr<VulkanBuffer> Staging;
|
||||||
|
@ -131,3 +122,27 @@ private:
|
||||||
void CreatePipeline(const VkPPRenderPassKey &key);
|
void CreatePipeline(const VkPPRenderPassKey &key);
|
||||||
void CreateRenderPass(const VkPPRenderPassKey &key);
|
void CreateRenderPass(const VkPPRenderPassKey &key);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class VkPPRenderState : public PPRenderState
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void Draw() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void RenderScreenQuad(VkPPRenderPassSetup *passSetup, VulkanDescriptorSet *descriptorSet, VulkanFramebuffer *framebuffer, int framebufferWidth, int framebufferHeight, int x, int y, int width, int height, const void *pushConstants, uint32_t pushConstantsSize);
|
||||||
|
|
||||||
|
VulkanDescriptorSet *GetInput(VkPPRenderPassSetup *passSetup, const TArray<PPTextureInput> &textures, bool bindShadowMapBuffers);
|
||||||
|
VulkanFramebuffer *GetOutput(VkPPRenderPassSetup *passSetup, const PPOutput &output, int &framebufferWidth, int &framebufferHeight);
|
||||||
|
|
||||||
|
VkPPShader *GetVkShader(PPShader *shader);
|
||||||
|
VkPPTexture *GetVkTexture(PPTexture *texture);
|
||||||
|
|
||||||
|
struct TextureImage
|
||||||
|
{
|
||||||
|
VulkanImage *image;
|
||||||
|
VulkanImageView *view;
|
||||||
|
VkImageLayout *layout;
|
||||||
|
const char *debugname;
|
||||||
|
};
|
||||||
|
TextureImage GetTexture(const PPTextureType &type, PPTexture *tex);
|
||||||
|
};
|
||||||
|
|
|
@ -89,6 +89,8 @@ VulkanFrameBuffer::~VulkanFrameBuffer()
|
||||||
for (VkHardwareTexture *cur = VkHardwareTexture::First; cur; cur = cur->Next)
|
for (VkHardwareTexture *cur = VkHardwareTexture::First; cur; cur = cur->Next)
|
||||||
cur->Reset();
|
cur->Reset();
|
||||||
|
|
||||||
|
PPResource::ResetAll();
|
||||||
|
|
||||||
delete MatricesUBO;
|
delete MatricesUBO;
|
||||||
delete StreamUBO;
|
delete StreamUBO;
|
||||||
delete mVertexData;
|
delete mVertexData;
|
||||||
|
|
Loading…
Reference in a new issue