mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-02-17 01:31:25 +00:00
- implement shadow maps
This commit is contained in:
parent
836938440c
commit
cce96ca87a
16 changed files with 200 additions and 26 deletions
|
@ -91,6 +91,7 @@ OpenGLFrameBuffer::~OpenGLFrameBuffer()
|
||||||
if (mSkyData != nullptr) delete mSkyData;
|
if (mSkyData != nullptr) delete mSkyData;
|
||||||
if (mViewpoints != nullptr) delete mViewpoints;
|
if (mViewpoints != nullptr) delete mViewpoints;
|
||||||
if (mLights != nullptr) delete mLights;
|
if (mLights != nullptr) delete mLights;
|
||||||
|
mShadowMap.Reset();
|
||||||
|
|
||||||
if (GLRenderer)
|
if (GLRenderer)
|
||||||
{
|
{
|
||||||
|
|
|
@ -8,7 +8,10 @@ enum
|
||||||
{
|
{
|
||||||
LIGHTBUF_BINDINGPOINT = 1,
|
LIGHTBUF_BINDINGPOINT = 1,
|
||||||
POSTPROCESS_BINDINGPOINT = 2,
|
POSTPROCESS_BINDINGPOINT = 2,
|
||||||
VIEWPOINT_BINDINGPOINT = 3
|
VIEWPOINT_BINDINGPOINT = 3,
|
||||||
|
LIGHTNODES_BINDINGPOINT = 4,
|
||||||
|
LIGHTLINES_BINDINGPOINT = 5,
|
||||||
|
LIGHTLIST_BINDINGPOINT = 6
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class UniformType
|
enum class UniformType
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "hwrenderer/utility/hw_cvars.h"
|
#include "hwrenderer/utility/hw_cvars.h"
|
||||||
#include "hwrenderer/dynlights/hw_dynlightdata.h"
|
#include "hwrenderer/dynlights/hw_dynlightdata.h"
|
||||||
#include "hwrenderer/data/buffers.h"
|
#include "hwrenderer/data/buffers.h"
|
||||||
|
#include "hwrenderer/data/shaderuniforms.h"
|
||||||
#include "stats.h"
|
#include "stats.h"
|
||||||
#include "g_levellocals.h"
|
#include "g_levellocals.h"
|
||||||
#include "v_video.h"
|
#include "v_video.h"
|
||||||
|
@ -188,7 +189,7 @@ void IShadowMap::UploadLights()
|
||||||
CollectLights();
|
CollectLights();
|
||||||
|
|
||||||
if (mLightList == nullptr)
|
if (mLightList == nullptr)
|
||||||
mLightList = screen->CreateDataBuffer(4, true);
|
mLightList = screen->CreateDataBuffer(LIGHTLIST_BINDINGPOINT, true);
|
||||||
|
|
||||||
mLightList->SetData(sizeof(float) * mLights.Size(), &mLights[0]);
|
mLightList->SetData(sizeof(float) * mLights.Size(), &mLights[0]);
|
||||||
}
|
}
|
||||||
|
@ -199,11 +200,11 @@ void IShadowMap::UploadAABBTree()
|
||||||
if (!ValidateAABBTree(&level))
|
if (!ValidateAABBTree(&level))
|
||||||
{
|
{
|
||||||
if (!mNodesBuffer)
|
if (!mNodesBuffer)
|
||||||
mNodesBuffer = screen->CreateDataBuffer(2, true);
|
mNodesBuffer = screen->CreateDataBuffer(LIGHTNODES_BINDINGPOINT, true);
|
||||||
mNodesBuffer->SetData(mAABBTree->NodesSize(), mAABBTree->Nodes());
|
mNodesBuffer->SetData(mAABBTree->NodesSize(), mAABBTree->Nodes());
|
||||||
|
|
||||||
if (!mLinesBuffer)
|
if (!mLinesBuffer)
|
||||||
mLinesBuffer = screen->CreateDataBuffer(3, true);
|
mLinesBuffer = screen->CreateDataBuffer(LIGHTLINES_BINDINGPOINT, true);
|
||||||
mLinesBuffer->SetData(mAABBTree->LinesSize(), mAABBTree->Lines());
|
mLinesBuffer->SetData(mAABBTree->LinesSize(), mAABBTree->Lines());
|
||||||
}
|
}
|
||||||
else if (mAABBTree->Update())
|
else if (mAABBTree->Update())
|
||||||
|
@ -213,10 +214,15 @@ void IShadowMap::UploadAABBTree()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IShadowMap::~IShadowMap()
|
void IShadowMap::Reset()
|
||||||
{
|
{
|
||||||
if (mLightList) delete mLightList;
|
delete mLightList; mLightList = nullptr;
|
||||||
if (mNodesBuffer) delete mNodesBuffer;
|
delete mNodesBuffer; mNodesBuffer = nullptr;
|
||||||
if (mLinesBuffer) delete mLinesBuffer;
|
delete mLinesBuffer; mLinesBuffer = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
IShadowMap::~IShadowMap()
|
||||||
|
{
|
||||||
|
Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,8 @@ public:
|
||||||
IShadowMap() { }
|
IShadowMap() { }
|
||||||
virtual ~IShadowMap();
|
virtual ~IShadowMap();
|
||||||
|
|
||||||
|
void Reset();
|
||||||
|
|
||||||
// Test if a world position is in shadow relative to the specified light and returns false if it is
|
// Test if a world position is in shadow relative to the specified light and returns false if it is
|
||||||
bool ShadowTest(FDynamicLight *light, const DVector3 &pos);
|
bool ShadowTest(FDynamicLight *light, const DVector3 &pos);
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ Postprocess::Postprocess()
|
||||||
Managers.Push(new PPTonemap());
|
Managers.Push(new PPTonemap());
|
||||||
Managers.Push(new PPAmbientOcclusion());
|
Managers.Push(new PPAmbientOcclusion());
|
||||||
Managers.Push(new PPPresent());
|
Managers.Push(new PPPresent());
|
||||||
|
Managers.Push(new PPShadowMap());
|
||||||
}
|
}
|
||||||
|
|
||||||
Postprocess::~Postprocess()
|
Postprocess::~Postprocess()
|
||||||
|
@ -892,3 +893,32 @@ void PPPresent::UpdateTextures()
|
||||||
void PPPresent::UpdateSteps()
|
void PPPresent::UpdateSteps()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void PPShadowMap::DeclareShaders()
|
||||||
|
{
|
||||||
|
hw_postprocess.Shaders["ShadowMap"] = { "shaders/glsl/shadowmap.fp", "", ShadowMapUniforms::Desc() };
|
||||||
|
}
|
||||||
|
|
||||||
|
void PPShadowMap::UpdateTextures()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void PPShadowMap::UpdateSteps()
|
||||||
|
{
|
||||||
|
ShadowMapUniforms uniforms;
|
||||||
|
uniforms.ShadowmapQuality = (float)gl_shadowmap_quality;
|
||||||
|
|
||||||
|
PPStep step;
|
||||||
|
step.ShaderName = "ShadowMap";
|
||||||
|
step.Uniforms.Set(uniforms);
|
||||||
|
step.Viewport = { 0, 0, gl_shadowmap_quality, 1024 };
|
||||||
|
step.SetShadowMapBuffers(true);
|
||||||
|
step.SetOutputShadowMap();
|
||||||
|
step.SetNoBlend();
|
||||||
|
|
||||||
|
TArray<PPStep> steps;
|
||||||
|
steps.Push(step);
|
||||||
|
hw_postprocess.Effects["UpdateShadowMap"] = steps;
|
||||||
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ typedef IntRect PPViewport;
|
||||||
|
|
||||||
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 };
|
enum class PPTextureType { CurrentPipelineTexture, NextPipelineTexture, PPTexture, SceneColor, SceneFog, SceneNormal, SceneDepth, SwapChain, ShadowMap };
|
||||||
|
|
||||||
class PPTextureInput
|
class PPTextureInput
|
||||||
{
|
{
|
||||||
|
@ -120,6 +120,11 @@ public:
|
||||||
tex.Texture = "";
|
tex.Texture = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetShadowMapBuffers(bool enable)
|
||||||
|
{
|
||||||
|
ShadowMapBuffers = enable;
|
||||||
|
}
|
||||||
|
|
||||||
void SetOutputTexture(PPTextureName texture)
|
void SetOutputTexture(PPTextureName texture)
|
||||||
{
|
{
|
||||||
Output.Type = PPTextureType::PPTexture;
|
Output.Type = PPTextureType::PPTexture;
|
||||||
|
@ -150,6 +155,12 @@ public:
|
||||||
Output.Texture = "";
|
Output.Texture = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetOutputShadowMap()
|
||||||
|
{
|
||||||
|
Output.Type = PPTextureType::ShadowMap;
|
||||||
|
Output.Texture = "";
|
||||||
|
}
|
||||||
|
|
||||||
void SetNoBlend()
|
void SetNoBlend()
|
||||||
{
|
{
|
||||||
BlendMode.BlendOp = STYLEOP_Add;
|
BlendMode.BlendOp = STYLEOP_Add;
|
||||||
|
@ -180,6 +191,7 @@ public:
|
||||||
PPViewport Viewport;
|
PPViewport Viewport;
|
||||||
PPBlendMode BlendMode;
|
PPBlendMode BlendMode;
|
||||||
PPOutput Output;
|
PPOutput Output;
|
||||||
|
bool ShadowMapBuffers = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class PixelFormat
|
enum class PixelFormat
|
||||||
|
@ -658,3 +670,11 @@ struct ShadowMapUniforms
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class PPShadowMap : public PPEffectManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void DeclareShaders() override;
|
||||||
|
void UpdateTextures() override;
|
||||||
|
void UpdateSteps() override;
|
||||||
|
};
|
||||||
|
|
|
@ -225,6 +225,23 @@ void VkPostprocess::ClearTonemapPalette()
|
||||||
hw_postprocess.Textures.Remove("Tonemap.Palette");
|
hw_postprocess.Textures.Remove("Tonemap.Palette");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VkPostprocess::UpdateShadowMap()
|
||||||
|
{
|
||||||
|
if (screen->mShadowMap.PerformUpdate())
|
||||||
|
{
|
||||||
|
RenderEffect("UpdateShadowMap");
|
||||||
|
|
||||||
|
auto fb = GetVulkanFrameBuffer();
|
||||||
|
auto buffers = fb->GetBuffers();
|
||||||
|
|
||||||
|
VkPPImageTransition imageTransition;
|
||||||
|
imageTransition.addImage(buffers->Shadowmap.get(), &buffers->ShadowmapLayout, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false);
|
||||||
|
imageTransition.execute(fb->GetDrawCommands());
|
||||||
|
|
||||||
|
screen->mShadowMap.FinishUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void VkPostprocess::BeginFrame()
|
void VkPostprocess::BeginFrame()
|
||||||
{
|
{
|
||||||
mFrameDescriptorSets.clear();
|
mFrameDescriptorSets.clear();
|
||||||
|
@ -233,6 +250,7 @@ void VkPostprocess::BeginFrame()
|
||||||
{
|
{
|
||||||
DescriptorPoolBuilder builder;
|
DescriptorPoolBuilder builder;
|
||||||
builder.addPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 100);
|
builder.addPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 100);
|
||||||
|
builder.addPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 4);
|
||||||
builder.setMaxSets(100);
|
builder.setMaxSets(100);
|
||||||
mDescriptorPool = builder.create(GetVulkanFrameBuffer()->device);
|
mDescriptorPool = builder.create(GetVulkanFrameBuffer()->device);
|
||||||
mDescriptorPool->SetDebugName("VkPostprocess.mDescriptorPool");
|
mDescriptorPool->SetDebugName("VkPostprocess.mDescriptorPool");
|
||||||
|
@ -405,10 +423,13 @@ void VkPostprocess::RenderEffect(const FString &name)
|
||||||
key.Uniforms = step.Uniforms.Data.Size();
|
key.Uniforms = step.Uniforms.Data.Size();
|
||||||
key.Shader = mShaders[step.ShaderName].get();
|
key.Shader = mShaders[step.ShaderName].get();
|
||||||
key.SwapChain = (step.Output.Type == PPTextureType::SwapChain);
|
key.SwapChain = (step.Output.Type == PPTextureType::SwapChain);
|
||||||
|
key.ShadowMapBuffers = step.ShadowMapBuffers;
|
||||||
if (step.Output.Type == PPTextureType::PPTexture)
|
if (step.Output.Type == PPTextureType::PPTexture)
|
||||||
key.OutputFormat = mTextures[step.Output.Texture]->Format;
|
key.OutputFormat = mTextures[step.Output.Texture]->Format;
|
||||||
else if (step.Output.Type == PPTextureType::SwapChain)
|
else if (step.Output.Type == PPTextureType::SwapChain)
|
||||||
key.OutputFormat = GetVulkanFrameBuffer()->swapChain->swapChainFormat.format;
|
key.OutputFormat = GetVulkanFrameBuffer()->swapChain->swapChainFormat.format;
|
||||||
|
else if (step.Output.Type == PPTextureType::ShadowMap)
|
||||||
|
key.OutputFormat = VK_FORMAT_R32_SFLOAT;
|
||||||
else
|
else
|
||||||
key.OutputFormat = VK_FORMAT_R16G16B16A16_SFLOAT;
|
key.OutputFormat = VK_FORMAT_R16G16B16A16_SFLOAT;
|
||||||
|
|
||||||
|
@ -417,7 +438,7 @@ void VkPostprocess::RenderEffect(const FString &name)
|
||||||
passSetup.reset(new VkPPRenderPassSetup(key));
|
passSetup.reset(new VkPPRenderPassSetup(key));
|
||||||
|
|
||||||
int framebufferWidth = 0, framebufferHeight = 0;
|
int framebufferWidth = 0, framebufferHeight = 0;
|
||||||
VulkanDescriptorSet *input = GetInput(passSetup.get(), step.Textures);
|
VulkanDescriptorSet *input = GetInput(passSetup.get(), step.Textures, step.ShadowMapBuffers);
|
||||||
VulkanFramebuffer *output = GetOutput(passSetup.get(), step.Output, framebufferWidth, framebufferHeight);
|
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());
|
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());
|
||||||
|
@ -470,7 +491,7 @@ void VkPostprocess::RenderScreenQuad(VkPPRenderPassSetup *passSetup, VulkanDescr
|
||||||
cmdbuffer->endRenderPass();
|
cmdbuffer->endRenderPass();
|
||||||
}
|
}
|
||||||
|
|
||||||
VulkanDescriptorSet *VkPostprocess::GetInput(VkPPRenderPassSetup *passSetup, const TArray<PPTextureInput> &textures)
|
VulkanDescriptorSet *VkPostprocess::GetInput(VkPPRenderPassSetup *passSetup, const TArray<PPTextureInput> &textures, bool bindShadowMapBuffers)
|
||||||
{
|
{
|
||||||
auto fb = GetVulkanFrameBuffer();
|
auto fb = GetVulkanFrameBuffer();
|
||||||
auto descriptors = mDescriptorPool->allocate(passSetup->DescriptorLayout.get());
|
auto descriptors = mDescriptorPool->allocate(passSetup->DescriptorLayout.get());
|
||||||
|
@ -489,6 +510,13 @@ VulkanDescriptorSet *VkPostprocess::GetInput(VkPPRenderPassSetup *passSetup, con
|
||||||
imageTransition.addImage(tex.image, tex.layout, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false);
|
imageTransition.addImage(tex.image, tex.layout, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bindShadowMapBuffers)
|
||||||
|
{
|
||||||
|
write.addBuffer(descriptors.get(), LIGHTNODES_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->LightNodes->mBuffer.get());
|
||||||
|
write.addBuffer(descriptors.get(), LIGHTLINES_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->LightLines->mBuffer.get());
|
||||||
|
write.addBuffer(descriptors.get(), LIGHTLIST_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->LightList->mBuffer.get());
|
||||||
|
}
|
||||||
|
|
||||||
write.updateSets(fb->device);
|
write.updateSets(fb->device);
|
||||||
imageTransition.execute(fb->GetDrawCommands());
|
imageTransition.execute(fb->GetDrawCommands());
|
||||||
|
|
||||||
|
@ -588,6 +616,13 @@ VkPostprocess::TextureImage VkPostprocess::GetTexture(const PPTextureType &type,
|
||||||
tex.layout = &fb->GetBuffers()->SceneDepthStencilLayout;
|
tex.layout = &fb->GetBuffers()->SceneDepthStencilLayout;
|
||||||
tex.debugname = "SceneDepth";
|
tex.debugname = "SceneDepth";
|
||||||
}
|
}
|
||||||
|
else if (type == PPTextureType::ShadowMap)
|
||||||
|
{
|
||||||
|
tex.image = fb->GetBuffers()->Shadowmap.get();
|
||||||
|
tex.view = fb->GetBuffers()->ShadowmapView.get();
|
||||||
|
tex.layout = &fb->GetBuffers()->ShadowmapLayout;
|
||||||
|
tex.debugname = "Shadowmap";
|
||||||
|
}
|
||||||
else if (type == PPTextureType::SwapChain)
|
else if (type == PPTextureType::SwapChain)
|
||||||
{
|
{
|
||||||
tex.image = nullptr;
|
tex.image = nullptr;
|
||||||
|
@ -639,6 +674,12 @@ void VkPPRenderPassSetup::CreateDescriptorLayout(const VkPPRenderPassKey &key)
|
||||||
DescriptorSetLayoutBuilder builder;
|
DescriptorSetLayoutBuilder builder;
|
||||||
for (int i = 0; i < key.InputTextures; i++)
|
for (int i = 0; i < key.InputTextures; i++)
|
||||||
builder.addBinding(i, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
builder.addBinding(i, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||||
|
if (key.ShadowMapBuffers)
|
||||||
|
{
|
||||||
|
builder.addBinding(LIGHTNODES_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||||
|
builder.addBinding(LIGHTLINES_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||||
|
builder.addBinding(LIGHTLIST_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||||
|
}
|
||||||
DescriptorLayout = builder.create(GetVulkanFrameBuffer()->device);
|
DescriptorLayout = builder.create(GetVulkanFrameBuffer()->device);
|
||||||
DescriptorLayout->SetDebugName("VkPPRenderPassSetup.DescriptorLayout");
|
DescriptorLayout->SetDebugName("VkPPRenderPassSetup.DescriptorLayout");
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ public:
|
||||||
PPBlendMode BlendMode;
|
PPBlendMode BlendMode;
|
||||||
VkFormat OutputFormat;
|
VkFormat OutputFormat;
|
||||||
int SwapChain;
|
int SwapChain;
|
||||||
|
int ShadowMapBuffers;
|
||||||
|
|
||||||
bool operator<(const VkPPRenderPassKey &other) const { return memcmp(this, &other, sizeof(VkPPRenderPassKey)) < 0; }
|
bool operator<(const VkPPRenderPassKey &other) const { return memcmp(this, &other, sizeof(VkPPRenderPassKey)) < 0; }
|
||||||
bool operator==(const VkPPRenderPassKey &other) const { return memcmp(this, &other, sizeof(VkPPRenderPassKey)) == 0; }
|
bool operator==(const VkPPRenderPassKey &other) const { return memcmp(this, &other, sizeof(VkPPRenderPassKey)) == 0; }
|
||||||
|
@ -60,6 +61,8 @@ public:
|
||||||
void BlurScene(float gameinfobluramount);
|
void BlurScene(float gameinfobluramount);
|
||||||
void ClearTonemapPalette();
|
void ClearTonemapPalette();
|
||||||
|
|
||||||
|
void UpdateShadowMap();
|
||||||
|
|
||||||
void BlitSceneToTexture();
|
void BlitSceneToTexture();
|
||||||
void BlitCurrentToImage(VulkanImage *image, VkImageLayout *layout, VkImageLayout finallayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
void BlitCurrentToImage(VulkanImage *image, VkImageLayout *layout, VkImageLayout finallayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||||
void DrawPresentTexture(const IntRect &box, bool applyGamma, bool clearBorders);
|
void DrawPresentTexture(const IntRect &box, bool applyGamma, bool clearBorders);
|
||||||
|
@ -72,7 +75,7 @@ private:
|
||||||
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);
|
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);
|
VulkanDescriptorSet *GetInput(VkPPRenderPassSetup *passSetup, const TArray<PPTextureInput> &textures, bool bindShadowMapBuffers);
|
||||||
VulkanFramebuffer *GetOutput(VkPPRenderPassSetup *passSetup, const PPOutput &output, int &framebufferWidth, int &framebufferHeight);
|
VulkanFramebuffer *GetOutput(VkPPRenderPassSetup *passSetup, const PPOutput &output, int &framebufferWidth, int &framebufferHeight);
|
||||||
VulkanSampler *GetSampler(PPFilterMode filter, PPWrapMode wrap);
|
VulkanSampler *GetSampler(PPFilterMode filter, PPWrapMode wrap);
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,8 @@ void VkRenderBuffers::BeginFrame(int width, int height, int sceneWidth, int scen
|
||||||
if (width != mWidth || height != mHeight || mSamples != samples)
|
if (width != mWidth || height != mHeight || mSamples != samples)
|
||||||
CreateScene(width, height, samples);
|
CreateScene(width, height, samples);
|
||||||
|
|
||||||
|
CreateShadowmap();
|
||||||
|
|
||||||
mWidth = width;
|
mWidth = width;
|
||||||
mHeight = height;
|
mHeight = height;
|
||||||
mSamples = samples;
|
mSamples = samples;
|
||||||
|
@ -206,3 +208,41 @@ void VkRenderBuffers::CreateSceneNormal(int width, int height, VkSampleCountFlag
|
||||||
SceneNormalView = viewbuilder.create(fb->device);
|
SceneNormalView = viewbuilder.create(fb->device);
|
||||||
SceneNormalView->SetDebugName("VkRenderBuffers.SceneNormalView");
|
SceneNormalView->SetDebugName("VkRenderBuffers.SceneNormalView");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VkRenderBuffers::CreateShadowmap()
|
||||||
|
{
|
||||||
|
if (Shadowmap && Shadowmap->width == gl_shadowmap_quality)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Shadowmap.reset();
|
||||||
|
ShadowmapView.reset();
|
||||||
|
|
||||||
|
auto fb = GetVulkanFrameBuffer();
|
||||||
|
|
||||||
|
ImageBuilder builder;
|
||||||
|
builder.setSize(gl_shadowmap_quality, 1024);
|
||||||
|
builder.setFormat(VK_FORMAT_R32_SFLOAT);
|
||||||
|
builder.setUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
|
||||||
|
Shadowmap = builder.create(fb->device);
|
||||||
|
Shadowmap->SetDebugName("VkRenderBuffers.Shadowmap");
|
||||||
|
|
||||||
|
ImageViewBuilder viewbuilder;
|
||||||
|
viewbuilder.setImage(Shadowmap.get(), VK_FORMAT_R32_SFLOAT);
|
||||||
|
ShadowmapView = viewbuilder.create(fb->device);
|
||||||
|
ShadowmapView->SetDebugName("VkRenderBuffers.ShadowmapView");
|
||||||
|
|
||||||
|
PipelineBarrier barrier;
|
||||||
|
barrier.addImage(Shadowmap.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 0, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
|
||||||
|
barrier.execute(fb->GetDrawCommands(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
|
||||||
|
|
||||||
|
if (!ShadowmapSampler)
|
||||||
|
{
|
||||||
|
SamplerBuilder builder;
|
||||||
|
builder.setMipmapMode(VK_SAMPLER_MIPMAP_MODE_NEAREST);
|
||||||
|
builder.setMinFilter(VK_FILTER_NEAREST);
|
||||||
|
builder.setMagFilter(VK_FILTER_NEAREST);
|
||||||
|
builder.setAddressMode(VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE);
|
||||||
|
ShadowmapSampler = builder.create(fb->device);
|
||||||
|
ShadowmapSampler->SetDebugName("VkRenderBuffers.ShadowmapSampler");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -37,6 +37,11 @@ public:
|
||||||
std::unique_ptr<VulkanImageView> PipelineView[NumPipelineImages];
|
std::unique_ptr<VulkanImageView> PipelineView[NumPipelineImages];
|
||||||
VkImageLayout PipelineLayout[NumPipelineImages];
|
VkImageLayout PipelineLayout[NumPipelineImages];
|
||||||
|
|
||||||
|
std::unique_ptr<VulkanImage> Shadowmap;
|
||||||
|
std::unique_ptr<VulkanImageView> ShadowmapView;
|
||||||
|
std::unique_ptr<VulkanSampler> ShadowmapSampler;
|
||||||
|
VkImageLayout ShadowmapLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void CreatePipeline(int width, int height);
|
void CreatePipeline(int width, int height);
|
||||||
void CreateScene(int width, int height, VkSampleCountFlagBits samples);
|
void CreateScene(int width, int height, VkSampleCountFlagBits samples);
|
||||||
|
@ -44,6 +49,7 @@ private:
|
||||||
void CreateSceneDepthStencil(int width, int height, VkSampleCountFlagBits samples);
|
void CreateSceneDepthStencil(int width, int height, VkSampleCountFlagBits samples);
|
||||||
void CreateSceneFog(int width, int height, VkSampleCountFlagBits samples);
|
void CreateSceneFog(int width, int height, VkSampleCountFlagBits samples);
|
||||||
void CreateSceneNormal(int width, int height, VkSampleCountFlagBits samples);
|
void CreateSceneNormal(int width, int height, VkSampleCountFlagBits samples);
|
||||||
|
void CreateShadowmap();
|
||||||
VkSampleCountFlagBits GetBestSampleCount();
|
VkSampleCountFlagBits GetBestSampleCount();
|
||||||
|
|
||||||
int mWidth = 0;
|
int mWidth = 0;
|
||||||
|
|
|
@ -79,6 +79,7 @@ void VkRenderPassManager::CreateDynamicSetLayout()
|
||||||
builder.addBinding(1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
builder.addBinding(1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||||
builder.addBinding(2, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT);
|
builder.addBinding(2, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||||
builder.addBinding(3, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT);
|
builder.addBinding(3, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||||
|
builder.addBinding(4, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||||
DynamicSetLayout = builder.create(GetVulkanFrameBuffer()->device);
|
DynamicSetLayout = builder.create(GetVulkanFrameBuffer()->device);
|
||||||
DynamicSetLayout->SetDebugName("VkRenderPassManager.DynamicSetLayout");
|
DynamicSetLayout->SetDebugName("VkRenderPassManager.DynamicSetLayout");
|
||||||
}
|
}
|
||||||
|
@ -90,7 +91,6 @@ void VkRenderPassManager::CreateTextureSetLayout()
|
||||||
{
|
{
|
||||||
builder.addBinding(i, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
builder.addBinding(i, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||||
}
|
}
|
||||||
builder.addBinding(16, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
|
||||||
TextureSetLayout = builder.create(GetVulkanFrameBuffer()->device);
|
TextureSetLayout = builder.create(GetVulkanFrameBuffer()->device);
|
||||||
TextureSetLayout->SetDebugName("VkRenderPassManager.TextureSetLayout");
|
TextureSetLayout->SetDebugName("VkRenderPassManager.TextureSetLayout");
|
||||||
}
|
}
|
||||||
|
@ -119,13 +119,18 @@ void VkRenderPassManager::CreateDescriptorPool()
|
||||||
void VkRenderPassManager::CreateDynamicSet()
|
void VkRenderPassManager::CreateDynamicSet()
|
||||||
{
|
{
|
||||||
DynamicSet = DescriptorPool->allocate(DynamicSetLayout.get());
|
DynamicSet = DescriptorPool->allocate(DynamicSetLayout.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
void VkRenderPassManager::UpdateDynamicSet()
|
||||||
|
{
|
||||||
auto fb = GetVulkanFrameBuffer();
|
auto fb = GetVulkanFrameBuffer();
|
||||||
|
|
||||||
WriteDescriptors update;
|
WriteDescriptors update;
|
||||||
update.addBuffer(DynamicSet.get(), 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->ViewpointUBO->mBuffer.get(), 0, sizeof(HWViewpointUniforms));
|
update.addBuffer(DynamicSet.get(), 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->ViewpointUBO->mBuffer.get(), 0, sizeof(HWViewpointUniforms));
|
||||||
update.addBuffer(DynamicSet.get(), 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, fb->LightBufferSSO->mBuffer.get(), 0, fb->GetLightBufferBlockSize());
|
update.addBuffer(DynamicSet.get(), 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, fb->LightBufferSSO->mBuffer.get(), 0, fb->GetLightBufferBlockSize());
|
||||||
update.addBuffer(DynamicSet.get(), 2, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->MatricesUBO->mBuffer.get(), 0, sizeof(MatricesUBO));
|
update.addBuffer(DynamicSet.get(), 2, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->MatricesUBO->mBuffer.get(), 0, sizeof(MatricesUBO));
|
||||||
update.addBuffer(DynamicSet.get(), 3, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->StreamUBO->mBuffer.get(), 0, sizeof(StreamUBO));
|
update.addBuffer(DynamicSet.get(), 3, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->StreamUBO->mBuffer.get(), 0, sizeof(StreamUBO));
|
||||||
|
update.addCombinedImageSampler(DynamicSet.get(), 4, fb->GetBuffers()->ShadowmapView.get(), fb->GetBuffers()->ShadowmapSampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||||
update.updateSets(fb->device);
|
update.updateSets(fb->device);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -68,6 +68,7 @@ public:
|
||||||
|
|
||||||
void Init();
|
void Init();
|
||||||
void RenderBuffersReset();
|
void RenderBuffersReset();
|
||||||
|
void UpdateDynamicSet();
|
||||||
|
|
||||||
VkRenderPassSetup *GetRenderPass(const VkRenderPassKey &key);
|
VkRenderPassSetup *GetRenderPass(const VkRenderPassKey &key);
|
||||||
int GetVertexFormat(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute *attrs);
|
int GetVertexFormat(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute *attrs);
|
||||||
|
|
|
@ -139,6 +139,8 @@ static const char *shaderBindings = R"(
|
||||||
StreamData data[256];
|
StreamData data[256];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
layout(set = 0, binding = 4) uniform sampler2D ShadowMap;
|
||||||
|
|
||||||
// textures
|
// textures
|
||||||
layout(set = 1, binding = 0) uniform sampler2D tex;
|
layout(set = 1, binding = 0) uniform sampler2D tex;
|
||||||
layout(set = 1, binding = 1) uniform sampler2D texture2;
|
layout(set = 1, binding = 1) uniform sampler2D texture2;
|
||||||
|
@ -146,7 +148,6 @@ static const char *shaderBindings = R"(
|
||||||
layout(set = 1, binding = 3) uniform sampler2D texture4;
|
layout(set = 1, binding = 3) uniform sampler2D texture4;
|
||||||
layout(set = 1, binding = 4) uniform sampler2D texture5;
|
layout(set = 1, binding = 4) uniform sampler2D texture5;
|
||||||
layout(set = 1, binding = 5) uniform sampler2D texture6;
|
layout(set = 1, binding = 5) uniform sampler2D texture6;
|
||||||
layout(set = 1, binding = 16) uniform sampler2D ShadowMap;
|
|
||||||
|
|
||||||
// This must match the PushConstants struct
|
// This must match the PushConstants struct
|
||||||
layout(push_constant) uniform PushConstants
|
layout(push_constant) uniform PushConstants
|
||||||
|
@ -207,7 +208,7 @@ static const char *shaderBindings = R"(
|
||||||
#define uSplitTopPlane data[uDataIndex].uSplitTopPlane
|
#define uSplitTopPlane data[uDataIndex].uSplitTopPlane
|
||||||
#define uSplitBottomPlane data[uDataIndex].uSplitBottomPlane
|
#define uSplitBottomPlane data[uDataIndex].uSplitBottomPlane
|
||||||
|
|
||||||
// #define SUPPORTS_SHADOWMAPS
|
#define SUPPORTS_SHADOWMAPS
|
||||||
#define VULKAN_COORDINATE_SYSTEM
|
#define VULKAN_COORDINATE_SYSTEM
|
||||||
#define HAS_UNIFORM_VERTEX_DATA
|
#define HAS_UNIFORM_VERTEX_DATA
|
||||||
)";
|
)";
|
||||||
|
|
|
@ -95,6 +95,7 @@ VulkanFrameBuffer::~VulkanFrameBuffer()
|
||||||
delete mSkyData;
|
delete mSkyData;
|
||||||
delete mViewpoints;
|
delete mViewpoints;
|
||||||
delete mLights;
|
delete mLights;
|
||||||
|
mShadowMap.Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanFrameBuffer::InitializeState()
|
void VulkanFrameBuffer::InitializeState()
|
||||||
|
@ -390,10 +391,8 @@ sector_t *VulkanFrameBuffer::RenderViewpoint(FRenderViewpoint &mainvp, AActor *
|
||||||
|
|
||||||
R_SetupFrame(mainvp, r_viewwindow, camera);
|
R_SetupFrame(mainvp, r_viewwindow, camera);
|
||||||
|
|
||||||
#if 0
|
|
||||||
if (mainview && toscreen)
|
if (mainview && toscreen)
|
||||||
UpdateShadowMap();
|
UpdateShadowMap();
|
||||||
#endif
|
|
||||||
|
|
||||||
// Update the attenuation flag of all light defaults for each viewpoint.
|
// Update the attenuation flag of all light defaults for each viewpoint.
|
||||||
// This function will only do something if the setting differs.
|
// This function will only do something if the setting differs.
|
||||||
|
@ -629,14 +628,19 @@ IIndexBuffer *VulkanFrameBuffer::CreateIndexBuffer()
|
||||||
IDataBuffer *VulkanFrameBuffer::CreateDataBuffer(int bindingpoint, bool ssbo)
|
IDataBuffer *VulkanFrameBuffer::CreateDataBuffer(int bindingpoint, bool ssbo)
|
||||||
{
|
{
|
||||||
auto buffer = new VKDataBuffer(bindingpoint, ssbo);
|
auto buffer = new VKDataBuffer(bindingpoint, ssbo);
|
||||||
if (bindingpoint == VIEWPOINT_BINDINGPOINT)
|
|
||||||
|
auto fb = GetVulkanFrameBuffer();
|
||||||
|
switch (bindingpoint)
|
||||||
{
|
{
|
||||||
ViewpointUBO = buffer;
|
case LIGHTBUF_BINDINGPOINT: LightBufferSSO = buffer; break;
|
||||||
}
|
case VIEWPOINT_BINDINGPOINT: ViewpointUBO = buffer; break;
|
||||||
else if (bindingpoint == LIGHTBUF_BINDINGPOINT)
|
case LIGHTNODES_BINDINGPOINT: LightNodes = buffer; break;
|
||||||
{
|
case LIGHTLINES_BINDINGPOINT: LightLines = buffer; break;
|
||||||
LightBufferSSO = buffer;
|
case LIGHTLIST_BINDINGPOINT: LightList = buffer; break;
|
||||||
|
case POSTPROCESS_BINDINGPOINT: break;
|
||||||
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -758,6 +762,7 @@ void VulkanFrameBuffer::BeginFrame()
|
||||||
mScreenBuffers->BeginFrame(screen->mScreenViewport.width, screen->mScreenViewport.height, screen->mSceneViewport.width, screen->mSceneViewport.height);
|
mScreenBuffers->BeginFrame(screen->mScreenViewport.width, screen->mScreenViewport.height, screen->mSceneViewport.width, screen->mSceneViewport.height);
|
||||||
mSaveBuffers->BeginFrame(SAVEPICWIDTH, SAVEPICHEIGHT, SAVEPICWIDTH, SAVEPICHEIGHT);
|
mSaveBuffers->BeginFrame(SAVEPICWIDTH, SAVEPICHEIGHT, SAVEPICWIDTH, SAVEPICHEIGHT);
|
||||||
mPostprocess->BeginFrame();
|
mPostprocess->BeginFrame();
|
||||||
|
mRenderPassManager->UpdateDynamicSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanFrameBuffer::Draw2D()
|
void VulkanFrameBuffer::Draw2D()
|
||||||
|
@ -841,3 +846,8 @@ void VulkanFrameBuffer::CreateFanToTrisIndexBuffer()
|
||||||
FanToTrisIndexBuffer.reset(CreateIndexBuffer());
|
FanToTrisIndexBuffer.reset(CreateIndexBuffer());
|
||||||
FanToTrisIndexBuffer->SetData(sizeof(uint32_t) * data.Size(), data.Data());
|
FanToTrisIndexBuffer->SetData(sizeof(uint32_t) * data.Size(), data.Data());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VulkanFrameBuffer::UpdateShadowMap()
|
||||||
|
{
|
||||||
|
mPostprocess->UpdateShadowMap();
|
||||||
|
}
|
||||||
|
|
|
@ -44,6 +44,10 @@ public:
|
||||||
VKDataBuffer *MatricesUBO = nullptr;
|
VKDataBuffer *MatricesUBO = nullptr;
|
||||||
VKDataBuffer *StreamUBO = nullptr;
|
VKDataBuffer *StreamUBO = nullptr;
|
||||||
|
|
||||||
|
VKDataBuffer *LightNodes = nullptr;
|
||||||
|
VKDataBuffer *LightLines = nullptr;
|
||||||
|
VKDataBuffer *LightList = nullptr;
|
||||||
|
|
||||||
std::unique_ptr<IIndexBuffer> FanToTrisIndexBuffer;
|
std::unique_ptr<IIndexBuffer> FanToTrisIndexBuffer;
|
||||||
|
|
||||||
std::vector<std::unique_ptr<VulkanBuffer>> mFrameDeleteList;
|
std::vector<std::unique_ptr<VulkanBuffer>> mFrameDeleteList;
|
||||||
|
@ -90,6 +94,7 @@ private:
|
||||||
void CreateFanToTrisIndexBuffer();
|
void CreateFanToTrisIndexBuffer();
|
||||||
void SubmitCommands(bool finish);
|
void SubmitCommands(bool finish);
|
||||||
void CopyScreenToBuffer(int w, int h, void *data);
|
void CopyScreenToBuffer(int w, int h, void *data);
|
||||||
|
void UpdateShadowMap();
|
||||||
|
|
||||||
std::unique_ptr<VkShaderManager> mShaderManager;
|
std::unique_ptr<VkShaderManager> mShaderManager;
|
||||||
std::unique_ptr<VkSamplerManager> mSamplerManager;
|
std::unique_ptr<VkSamplerManager> mSamplerManager;
|
||||||
|
|
|
@ -20,17 +20,17 @@ struct GPULine
|
||||||
vec2 delta; // Line end position - line start position
|
vec2 delta; // Line end position - line start position
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(std430, binding = 2) buffer LightNodes
|
layout(std430, binding = 4) buffer LightNodes
|
||||||
{
|
{
|
||||||
GPUNode nodes[];
|
GPUNode nodes[];
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(std430, binding = 3) buffer LightLines
|
layout(std430, binding = 5) buffer LightLines
|
||||||
{
|
{
|
||||||
GPULine lines[];
|
GPULine lines[];
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(std430, binding = 4) buffer LightList
|
layout(std430, binding = 6) buffer LightList
|
||||||
{
|
{
|
||||||
vec4 lights[];
|
vec4 lights[];
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue