mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-02-17 01:31:25 +00:00
Let the backend manage the shadowmap buffers
This commit is contained in:
parent
930107636e
commit
b413c80e49
11 changed files with 49 additions and 140 deletions
|
@ -92,7 +92,7 @@ bool ShadowMap::ShadowTest(const DVector3 &lpos, const DVector3 &pos)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ShadowMap::PerformUpdate()
|
||||
void ShadowMap::PerformUpdate()
|
||||
{
|
||||
UpdateCycles.Reset();
|
||||
|
||||
|
@ -103,55 +103,18 @@ bool ShadowMap::PerformUpdate()
|
|||
if (CollectLights != nullptr)
|
||||
{
|
||||
UpdateCycles.Clock();
|
||||
UploadAABBTree();
|
||||
UploadLights();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ShadowMap::UploadLights()
|
||||
{
|
||||
mLights.Resize(1024 * 4);
|
||||
CollectLights();
|
||||
mLights.Resize(1024 * 4);
|
||||
CollectLights();
|
||||
|
||||
if (mLightList == nullptr)
|
||||
mLightList = fb->CreateShadowmapLightsBuffer();
|
||||
|
||||
mLightList->SetData(sizeof(float) * mLights.Size(), &mLights[0], BufferUsageType::Stream);
|
||||
}
|
||||
|
||||
|
||||
void ShadowMap::UploadAABBTree()
|
||||
{
|
||||
if (mNewTree)
|
||||
{
|
||||
fb->SetShadowMaps(mLights, mAABBTree, mNewTree);
|
||||
mNewTree = false;
|
||||
|
||||
if (!mNodesBuffer)
|
||||
mNodesBuffer = fb->CreateShadowmapNodesBuffer();
|
||||
mNodesBuffer->SetData(mAABBTree->NodesSize(), mAABBTree->Nodes(), BufferUsageType::Static);
|
||||
|
||||
if (!mLinesBuffer)
|
||||
mLinesBuffer = fb->CreateShadowmapLinesBuffer();
|
||||
mLinesBuffer->SetData(mAABBTree->LinesSize(), mAABBTree->Lines(), BufferUsageType::Static);
|
||||
UpdateCycles.Unclock();
|
||||
}
|
||||
else if (mAABBTree->Update())
|
||||
{
|
||||
mNodesBuffer->SetSubData(mAABBTree->DynamicNodesOffset(), mAABBTree->DynamicNodesSize(), mAABBTree->DynamicNodes());
|
||||
mLinesBuffer->SetSubData(mAABBTree->DynamicLinesOffset(), mAABBTree->DynamicLinesSize(), mAABBTree->DynamicLines());
|
||||
}
|
||||
}
|
||||
|
||||
void ShadowMap::Reset()
|
||||
{
|
||||
delete mLightList; mLightList = nullptr;
|
||||
delete mNodesBuffer; mNodesBuffer = nullptr;
|
||||
delete mLinesBuffer; mLinesBuffer = nullptr;
|
||||
}
|
||||
|
||||
ShadowMap::~ShadowMap()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
|
|
|
@ -17,8 +17,6 @@ public:
|
|||
ShadowMap(DFrameBuffer* fb) : fb(fb) { }
|
||||
virtual ~ShadowMap();
|
||||
|
||||
void Reset();
|
||||
|
||||
// Test if a world position is in shadow relative to the specified light and returns false if it is
|
||||
bool ShadowTest(const DVector3 &lpos, const DVector3 &pos);
|
||||
|
||||
|
@ -26,11 +24,7 @@ public:
|
|||
static int LightsProcessed;
|
||||
static int LightsShadowmapped;
|
||||
|
||||
bool PerformUpdate();
|
||||
void FinishUpdate()
|
||||
{
|
||||
UpdateCycles.Clock();
|
||||
}
|
||||
void PerformUpdate();
|
||||
|
||||
unsigned int NodesCount() const
|
||||
{
|
||||
|
@ -67,10 +61,6 @@ public:
|
|||
}
|
||||
|
||||
protected:
|
||||
// Upload the AABB-tree to the GPU
|
||||
void UploadAABBTree();
|
||||
void UploadLights();
|
||||
|
||||
// Working buffer for creating the list of lights. Stored here to avoid allocating memory each frame
|
||||
TArray<float> mLights;
|
||||
|
||||
|
@ -81,15 +71,6 @@ protected:
|
|||
ShadowMap(const ShadowMap &) = delete;
|
||||
ShadowMap &operator=(ShadowMap &) = delete;
|
||||
|
||||
// OpenGL storage buffer with the list of lights in the shadow map texture
|
||||
// These buffers need to be accessed by the OpenGL backend directly so that they can be bound.
|
||||
public:
|
||||
IBuffer* mLightList = nullptr;
|
||||
|
||||
// OpenGL storage buffers for the AABB tree
|
||||
IBuffer* mNodesBuffer = nullptr;
|
||||
IBuffer* mLinesBuffer = nullptr;
|
||||
|
||||
std::function<void()> CollectLights = nullptr;
|
||||
|
||||
};
|
||||
|
|
|
@ -157,10 +157,6 @@ public:
|
|||
virtual bool IsVulkan() { return false; }
|
||||
virtual bool IsPoly() { return false; }
|
||||
virtual bool CompileNextShader() { return true; }
|
||||
void SetAABBTree(hwrenderer::LevelAABBTree * tree)
|
||||
{
|
||||
mShadowMap->SetAABBTree(tree);
|
||||
}
|
||||
virtual void SetLevelMesh(hwrenderer::LevelMesh *mesh) { }
|
||||
bool allowSSBO() const
|
||||
{
|
||||
|
@ -233,11 +229,6 @@ public:
|
|||
virtual IBuffer* CreateIndexBuffer() { return nullptr; }
|
||||
bool BuffersArePersistent() { return !!(hwcaps & RFL_BUFFER_STORAGE); }
|
||||
|
||||
// To do: these buffers shouldn't be created by the hwrenderer layer - it will be simpler if the backend manages them completely
|
||||
virtual IBuffer* CreateShadowmapNodesBuffer() { return nullptr; }
|
||||
virtual IBuffer* CreateShadowmapLinesBuffer() { return nullptr; }
|
||||
virtual IBuffer* CreateShadowmapLightsBuffer() { return nullptr; }
|
||||
|
||||
// This is overridable in case Vulkan does it differently.
|
||||
virtual bool RenderTextureIsFlipped() const
|
||||
{
|
||||
|
@ -252,7 +243,7 @@ public:
|
|||
virtual void FirstEye() {}
|
||||
virtual void NextEye(int eyecount) {}
|
||||
virtual void SetSceneRenderTarget(bool useSSAO) {}
|
||||
virtual void UpdateShadowMap() {}
|
||||
virtual void SetShadowMaps(const TArray<float>& lights, hwrenderer::LevelAABBTree* tree, bool newTree) {}
|
||||
virtual void WaitForCommands(bool finish) {}
|
||||
virtual void SetSaveBuffers(bool yes) {}
|
||||
virtual void ImageTransitionScene(bool unknown) {}
|
||||
|
|
|
@ -49,6 +49,10 @@ void VkBufferManager::Init()
|
|||
Bonebuffer.SSO.reset(new VkHardwareDataBuffer(fb, true, false));
|
||||
Bonebuffer.SSO->SetData(Bonebuffer.Count * sizeof(VSMatrix), nullptr, BufferUsageType::Persistent);
|
||||
|
||||
Shadowmap.Nodes.reset(new VkHardwareDataBuffer(fb, true, false));
|
||||
Shadowmap.Lines.reset(new VkHardwareDataBuffer(fb, true, false));
|
||||
Shadowmap.Lights.reset(new VkHardwareDataBuffer(fb, true, false));
|
||||
|
||||
CreateFanToTrisIndexBuffer();
|
||||
}
|
||||
|
||||
|
@ -57,6 +61,9 @@ void VkBufferManager::Deinit()
|
|||
Viewpoint.UBO.reset();
|
||||
Lightbuffer.SSO.reset();
|
||||
Bonebuffer.SSO.reset();
|
||||
Shadowmap.Nodes.reset();
|
||||
Shadowmap.Lines.reset();
|
||||
Shadowmap.Lights.reset();
|
||||
|
||||
while (!Buffers.empty())
|
||||
RemoveBuffer(Buffers.back());
|
||||
|
@ -72,11 +79,6 @@ void VkBufferManager::RemoveBuffer(VkHardwareBuffer* buffer)
|
|||
buffer->Reset();
|
||||
buffer->fb = nullptr;
|
||||
Buffers.erase(buffer->it);
|
||||
|
||||
for (VkHardwareDataBuffer** knownbuf : { &LightNodes, &LightLines, &LightList})
|
||||
{
|
||||
if (buffer == *knownbuf) *knownbuf = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
IBuffer* VkBufferManager::CreateVertexBuffer(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute* attrs)
|
||||
|
@ -89,24 +91,6 @@ IBuffer* VkBufferManager::CreateIndexBuffer()
|
|||
return new VkHardwareIndexBuffer(fb);
|
||||
}
|
||||
|
||||
IBuffer* VkBufferManager::CreateShadowmapNodesBuffer()
|
||||
{
|
||||
LightNodes = new VkHardwareDataBuffer(fb, true, false);
|
||||
return LightNodes;
|
||||
}
|
||||
|
||||
IBuffer* VkBufferManager::CreateShadowmapLinesBuffer()
|
||||
{
|
||||
LightLines = new VkHardwareDataBuffer(fb, true, false);
|
||||
return LightLines;
|
||||
}
|
||||
|
||||
IBuffer* VkBufferManager::CreateShadowmapLightsBuffer()
|
||||
{
|
||||
LightList = new VkHardwareDataBuffer(fb, true, false);
|
||||
return LightList;
|
||||
}
|
||||
|
||||
void VkBufferManager::CreateFanToTrisIndexBuffer()
|
||||
{
|
||||
TArray<uint32_t> data;
|
||||
|
|
|
@ -24,10 +24,6 @@ public:
|
|||
IBuffer* CreateVertexBuffer(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute* attrs);
|
||||
IBuffer* CreateIndexBuffer();
|
||||
|
||||
IBuffer* CreateShadowmapNodesBuffer();
|
||||
IBuffer* CreateShadowmapLinesBuffer();
|
||||
IBuffer* CreateShadowmapLightsBuffer();
|
||||
|
||||
void AddBuffer(VkHardwareBuffer* buffer);
|
||||
void RemoveBuffer(VkHardwareBuffer* buffer);
|
||||
|
||||
|
@ -53,9 +49,12 @@ public:
|
|||
std::unique_ptr<VkHardwareDataBuffer> SSO;
|
||||
} Bonebuffer;
|
||||
|
||||
VkHardwareDataBuffer* LightNodes = nullptr;
|
||||
VkHardwareDataBuffer* LightLines = nullptr;
|
||||
VkHardwareDataBuffer* LightList = nullptr;
|
||||
struct
|
||||
{
|
||||
std::unique_ptr<VkHardwareDataBuffer> Nodes;
|
||||
std::unique_ptr<VkHardwareDataBuffer> Lines;
|
||||
std::unique_ptr<VkHardwareDataBuffer> Lights;
|
||||
} Shadowmap;
|
||||
|
||||
std::unique_ptr<VkStreamBuffer> MatrixBuffer;
|
||||
std::unique_ptr<VkStreamBuffer> StreamBuffer;
|
||||
|
|
|
@ -220,9 +220,9 @@ VulkanDescriptorSet* VkDescriptorSetManager::GetInput(VkPPRenderPassSetup* passS
|
|||
|
||||
if (bindShadowMapBuffers)
|
||||
{
|
||||
write.AddBuffer(descriptors.get(), 4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetBufferManager()->LightNodes->mBuffer.get());
|
||||
write.AddBuffer(descriptors.get(), 5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetBufferManager()->LightLines->mBuffer.get());
|
||||
write.AddBuffer(descriptors.get(), 6, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetBufferManager()->LightList->mBuffer.get());
|
||||
write.AddBuffer(descriptors.get(), 4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetBufferManager()->Shadowmap.Nodes->mBuffer.get());
|
||||
write.AddBuffer(descriptors.get(), 5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetBufferManager()->Shadowmap.Lines->mBuffer.get());
|
||||
write.AddBuffer(descriptors.get(), 6, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetBufferManager()->Shadowmap.Lights->mBuffer.get());
|
||||
}
|
||||
|
||||
write.Execute(fb->GetDevice());
|
||||
|
|
|
@ -275,17 +275,12 @@ void VkPostprocess::ClearTonemapPalette()
|
|||
|
||||
void VkPostprocess::UpdateShadowMap()
|
||||
{
|
||||
if (screen->mShadowMap->PerformUpdate())
|
||||
{
|
||||
VkPPRenderState renderstate(fb);
|
||||
hw_postprocess.shadowmap.Update(&renderstate);
|
||||
VkPPRenderState renderstate(fb);
|
||||
hw_postprocess.shadowmap.Update(&renderstate);
|
||||
|
||||
VkImageTransition()
|
||||
.AddImage(&fb->GetTextureManager()->Shadowmap, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false)
|
||||
.Execute(fb->GetCommands()->GetDrawCommands());
|
||||
|
||||
screen->mShadowMap->FinishUpdate();
|
||||
}
|
||||
VkImageTransition()
|
||||
.AddImage(&fb->GetTextureManager()->Shadowmap, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false)
|
||||
.Execute(fb->GetCommands()->GetDrawCommands());
|
||||
}
|
||||
|
||||
void VkPostprocess::NextEye(int eyeCount)
|
||||
|
|
|
@ -313,21 +313,6 @@ IBuffer*VulkanRenderDevice::CreateIndexBuffer()
|
|||
return GetBufferManager()->CreateIndexBuffer();
|
||||
}
|
||||
|
||||
IBuffer* VulkanRenderDevice::CreateShadowmapNodesBuffer()
|
||||
{
|
||||
return GetBufferManager()->CreateShadowmapNodesBuffer();
|
||||
}
|
||||
|
||||
IBuffer* VulkanRenderDevice::CreateShadowmapLinesBuffer()
|
||||
{
|
||||
return GetBufferManager()->CreateShadowmapLinesBuffer();
|
||||
}
|
||||
|
||||
IBuffer* VulkanRenderDevice::CreateShadowmapLightsBuffer()
|
||||
{
|
||||
return GetBufferManager()->CreateShadowmapLightsBuffer();
|
||||
}
|
||||
|
||||
void VulkanRenderDevice::SetTextureFilterMode()
|
||||
{
|
||||
if (mSamplerManager)
|
||||
|
@ -531,8 +516,23 @@ void VulkanRenderDevice::SetLevelMesh(hwrenderer::LevelMesh* mesh)
|
|||
mRaytrace->SetLevelMesh(mesh);
|
||||
}
|
||||
|
||||
void VulkanRenderDevice::UpdateShadowMap()
|
||||
void VulkanRenderDevice::SetShadowMaps(const TArray<float>& lights, hwrenderer::LevelAABBTree* tree, bool newTree)
|
||||
{
|
||||
auto buffers = GetBufferManager();
|
||||
|
||||
buffers->Shadowmap.Lights->SetData(sizeof(float) * lights.Size(), lights.Data(), BufferUsageType::Stream);
|
||||
|
||||
if (newTree)
|
||||
{
|
||||
buffers->Shadowmap.Nodes->SetData(tree->NodesSize(), tree->Nodes(), BufferUsageType::Static);
|
||||
buffers->Shadowmap.Lines->SetData(tree->LinesSize(), tree->Lines(), BufferUsageType::Static);
|
||||
}
|
||||
else if (tree->Update())
|
||||
{
|
||||
buffers->Shadowmap.Nodes->SetSubData(tree->DynamicNodesOffset(), tree->DynamicNodesSize(), tree->DynamicNodes());
|
||||
buffers->Shadowmap.Lines->SetSubData(tree->DynamicLinesOffset(), tree->DynamicLinesSize(), tree->DynamicLines());
|
||||
}
|
||||
|
||||
mPostprocess->UpdateShadowMap();
|
||||
}
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ public:
|
|||
void AmbientOccludeScene(float m5) override;
|
||||
void SetSceneRenderTarget(bool useSSAO) override;
|
||||
void SetLevelMesh(hwrenderer::LevelMesh* mesh) override;
|
||||
void UpdateShadowMap() override;
|
||||
void SetShadowMaps(const TArray<float>& lights, hwrenderer::LevelAABBTree* tree, bool newTree) override;
|
||||
void SetSaveBuffers(bool yes) override;
|
||||
void ImageTransitionScene(bool unknown) override;
|
||||
void SetActiveRenderTarget() override;
|
||||
|
@ -74,10 +74,6 @@ public:
|
|||
IBuffer* CreateVertexBuffer(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute* attrs) override;
|
||||
IBuffer* CreateIndexBuffer() override;
|
||||
|
||||
IBuffer* CreateShadowmapNodesBuffer() override;
|
||||
IBuffer* CreateShadowmapLinesBuffer() override;
|
||||
IBuffer* CreateShadowmapLightsBuffer() override;
|
||||
|
||||
FTexture *WipeStartScreen() override;
|
||||
FTexture *WipeEndScreen() override;
|
||||
|
||||
|
|
|
@ -376,7 +376,7 @@ void FLevelLocals::ClearLevelData(bool fullgc)
|
|||
aabbTree = nullptr;
|
||||
levelMesh = nullptr;
|
||||
if (screen)
|
||||
screen->SetAABBTree(nullptr);
|
||||
screen->mShadowMap->SetAABBTree(nullptr);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -110,16 +110,16 @@ sector_t* RenderViewpoint(FRenderViewpoint& mainvp, AActor* camera, IntRect* bou
|
|||
|
||||
if (mainview && toscreen && !(camera->Level->flags3 & LEVEL3_NOSHADOWMAP) && camera->Level->HasDynamicLights && gl_light_shadowmap && screen->allowSSBO() && (screen->hwcaps & RFL_SHADER_STORAGE_BUFFER))
|
||||
{
|
||||
screen->SetAABBTree(camera->Level->aabbTree);
|
||||
screen->mShadowMap->SetAABBTree(camera->Level->aabbTree);
|
||||
screen->mShadowMap->SetCollectLights([=] {
|
||||
CollectLights(camera->Level);
|
||||
});
|
||||
screen->UpdateShadowMap();
|
||||
screen->mShadowMap->PerformUpdate();
|
||||
}
|
||||
else
|
||||
{
|
||||
// null all references to the level if we do not need a shadowmap. This will shortcut all internal calculations without further checks.
|
||||
screen->SetAABBTree(nullptr);
|
||||
screen->mShadowMap->SetAABBTree(nullptr);
|
||||
screen->mShadowMap->SetCollectLights(nullptr);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue