diff --git a/src/common/rendering/hwrenderer/data/hw_shadowmap.cpp b/src/common/rendering/hwrenderer/data/hw_shadowmap.cpp index b6bf4e924..70eb42208 100644 --- a/src/common/rendering/hwrenderer/data/hw_shadowmap.cpp +++ b/src/common/rendering/hwrenderer/data/hw_shadowmap.cpp @@ -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(); } diff --git a/src/common/rendering/hwrenderer/data/hw_shadowmap.h b/src/common/rendering/hwrenderer/data/hw_shadowmap.h index 1900b4094..5cc754120 100644 --- a/src/common/rendering/hwrenderer/data/hw_shadowmap.h +++ b/src/common/rendering/hwrenderer/data/hw_shadowmap.h @@ -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 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 CollectLights = nullptr; - }; diff --git a/src/common/rendering/v_video.h b/src/common/rendering/v_video.h index 233b0cfd4..971019680 100644 --- a/src/common/rendering/v_video.h +++ b/src/common/rendering/v_video.h @@ -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& lights, hwrenderer::LevelAABBTree* tree, bool newTree) {} virtual void WaitForCommands(bool finish) {} virtual void SetSaveBuffers(bool yes) {} virtual void ImageTransitionScene(bool unknown) {} diff --git a/src/common/rendering/vulkan/buffers/vk_buffer.cpp b/src/common/rendering/vulkan/buffers/vk_buffer.cpp index c34d3bfe9..cab8cf460 100644 --- a/src/common/rendering/vulkan/buffers/vk_buffer.cpp +++ b/src/common/rendering/vulkan/buffers/vk_buffer.cpp @@ -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 data; diff --git a/src/common/rendering/vulkan/buffers/vk_buffer.h b/src/common/rendering/vulkan/buffers/vk_buffer.h index 57ffd3439..491dfbee6 100644 --- a/src/common/rendering/vulkan/buffers/vk_buffer.h +++ b/src/common/rendering/vulkan/buffers/vk_buffer.h @@ -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 SSO; } Bonebuffer; - VkHardwareDataBuffer* LightNodes = nullptr; - VkHardwareDataBuffer* LightLines = nullptr; - VkHardwareDataBuffer* LightList = nullptr; + struct + { + std::unique_ptr Nodes; + std::unique_ptr Lines; + std::unique_ptr Lights; + } Shadowmap; std::unique_ptr MatrixBuffer; std::unique_ptr StreamBuffer; diff --git a/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.cpp b/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.cpp index ca83a6092..b25ad41a5 100644 --- a/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.cpp +++ b/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.cpp @@ -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()); diff --git a/src/common/rendering/vulkan/vk_postprocess.cpp b/src/common/rendering/vulkan/vk_postprocess.cpp index 9a8e5cf08..fb858058d 100644 --- a/src/common/rendering/vulkan/vk_postprocess.cpp +++ b/src/common/rendering/vulkan/vk_postprocess.cpp @@ -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) diff --git a/src/common/rendering/vulkan/vk_renderdevice.cpp b/src/common/rendering/vulkan/vk_renderdevice.cpp index fc0702e43..b9479cbdd 100644 --- a/src/common/rendering/vulkan/vk_renderdevice.cpp +++ b/src/common/rendering/vulkan/vk_renderdevice.cpp @@ -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) @@ -530,8 +515,23 @@ void VulkanRenderDevice::SetLevelMesh(hwrenderer::LevelMesh* mesh) mRaytrace->SetLevelMesh(mesh); } -void VulkanRenderDevice::UpdateShadowMap() +void VulkanRenderDevice::SetShadowMaps(const TArray& 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(); } diff --git a/src/common/rendering/vulkan/vk_renderdevice.h b/src/common/rendering/vulkan/vk_renderdevice.h index f569f18c6..4dc73e1b1 100644 --- a/src/common/rendering/vulkan/vk_renderdevice.h +++ b/src/common/rendering/vulkan/vk_renderdevice.h @@ -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& 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; diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 569f79919..17ff41ae8 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -376,7 +376,7 @@ void FLevelLocals::ClearLevelData(bool fullgc) aabbTree = nullptr; levelMesh = nullptr; if (screen) - screen->SetAABBTree(nullptr); + screen->mShadowMap->SetAABBTree(nullptr); } //========================================================================== diff --git a/src/rendering/hwrenderer/hw_entrypoint.cpp b/src/rendering/hwrenderer/hw_entrypoint.cpp index 704e446c6..e863e6d22 100644 --- a/src/rendering/hwrenderer/hw_entrypoint.cpp +++ b/src/rendering/hwrenderer/hw_entrypoint.cpp @@ -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); }