From 995de6f71d742e2c70b02692b5929fb6b7e575a9 Mon Sep 17 00:00:00 2001 From: RaveYard <29225776+MrRaveYard@users.noreply.github.com> Date: Sat, 9 Sep 2023 10:11:43 +0200 Subject: [PATCH] Update lightmapper and add limiter to updates --- .../hwrenderer/data/hw_renderstate.h | 6 +- .../vulkan/accelstructs/vk_lightmap.cpp | 92 ++++++++++++------- .../vulkan/accelstructs/vk_lightmap.h | 6 +- src/rendering/hwrenderer/hw_entrypoint.cpp | 20 +++- 4 files changed, 88 insertions(+), 36 deletions(-) diff --git a/src/common/rendering/hwrenderer/data/hw_renderstate.h b/src/common/rendering/hwrenderer/data/hw_renderstate.h index 6187eee2b1..90c53ff8a1 100644 --- a/src/common/rendering/hwrenderer/data/hw_renderstate.h +++ b/src/common/rendering/hwrenderer/data/hw_renderstate.h @@ -10,6 +10,8 @@ #include "hw_viewpointuniforms.h" #include "hw_cvars.h" +EXTERN_CVAR(Int, lm_max_updates); + struct FColormap; class IBuffer; struct HWViewpointUniforms; @@ -733,11 +735,11 @@ public: inline void PushVisibleSurface(int surfaceIndex, LevelMeshSurface* surface) { - if(surface->needsUpdate && mActiveLightmapSurfaces.Find(surfaceIndex) >= mActiveLightmapSurfaces.Size()) // yikes, how awful + if(surface->needsUpdate && mActiveLightmapSurfaces.Size() < lm_max_updates && mActiveLightmapSurfaces.Find(surfaceIndex) >= mActiveLightmapSurfaces.Size()) // yikes, how awful mActiveLightmapSurfaces.Push(surfaceIndex); } - inline const auto& GetVisibleSurfaceList() const + inline auto& GetVisibleSurfaceList() { return mActiveLightmapSurfaces; } diff --git a/src/common/rendering/vulkan/accelstructs/vk_lightmap.cpp b/src/common/rendering/vulkan/accelstructs/vk_lightmap.cpp index 03f3cdb74e..0f30bfe453 100644 --- a/src/common/rendering/vulkan/accelstructs/vk_lightmap.cpp +++ b/src/common/rendering/vulkan/accelstructs/vk_lightmap.cpp @@ -9,6 +9,21 @@ #include "filesystem.h" #include "cmdlib.h" +static int lastSurfaceCount; +static glcycle_t lightmapRaytrace; +static glcycle_t lightmapRaytraceLast; + +ADD_STAT(lightmapper) +{ + FString out; + out.Format("last: %.3fms\ntotal: %3.fms\nLast batch surface count: %d", lightmapRaytraceLast.TimeMS(), lightmapRaytrace.TimeMS(), lastSurfaceCount); + return out; +} + +CVAR(Int, lm_background_updates, 8, CVAR_NOSAVE); +CVAR(Int, lm_max_updates, 128, CVAR_NOSAVE); + + VkLightmap::VkLightmap(VulkanRenderDevice* fb) : fb(fb) { useRayQuery = fb->GetDevice()->PhysicalDevice.Features.RayQuery.rayQuery; @@ -31,18 +46,9 @@ VkLightmap::~VkLightmap() lights.Buffer->Unmap(); } -static int lastSurfaceCount; -static glcycle_t lightmapRaytrace; -static glcycle_t lightmapRaytraceLast; - -ADD_STAT(lightmapper) -{ - FString out; - out.Format("last: %.3fms\ntotal: %3.fms\nLast batch surface count: %d", lightmapRaytraceLast.TimeMS(), lightmapRaytrace.TimeMS(), lastSurfaceCount); - return out; -} - +#if 0 #include +#endif void VkLightmap::Raytrace(LevelMesh* level, const TArray& surfaceIndices) { @@ -52,7 +58,6 @@ void VkLightmap::Raytrace(LevelMesh* level, const TArray& surfaceIndices) if (newLevel) { UpdateAccelStructDescriptors(); - CreateAtlasImages(); lightmapRaytrace.Reset(); lightmapRaytraceLast.Reset(); @@ -64,6 +69,8 @@ void VkLightmap::Raytrace(LevelMesh* level, const TArray& surfaceIndices) lightmapRaytrace.Clock(); lightmapRaytraceLast.ResetAndClock(); + CreateAtlasImages(surfaceIndices); + #if 0 TArray allSurfaces; @@ -99,14 +106,20 @@ void VkLightmap::Raytrace(LevelMesh* level, const TArray& surfaceIndices) for (size_t pageIndex = 0; pageIndex < atlasImages.size(); pageIndex++) { - RenderAtlasImage(pageIndex, allSurfaces); + if (atlasImages[pageIndex].pageMaxX && atlasImages[pageIndex].pageMaxY) + { + RenderAtlasImage(pageIndex, allSurfaces); + } } for (size_t pageIndex = 0; pageIndex < atlasImages.size(); pageIndex++) { - ResolveAtlasImage(pageIndex); - BlurAtlasImage(pageIndex); - CopyAtlasImageResult(pageIndex, allSurfaces); + if (atlasImages[pageIndex].pageMaxX && atlasImages[pageIndex].pageMaxY) + { + ResolveAtlasImage(pageIndex); + BlurAtlasImage(pageIndex); + CopyAtlasImageResult(pageIndex, allSurfaces); + } } lightmapRaytrace.Unclock(); @@ -246,24 +259,39 @@ void VkLightmap::RenderAtlasImage(size_t pageIndex, const TArray& surfaceIn fb->GetCommands()->GetTransferCommands()->endRenderPass(); } -void VkLightmap::CreateAtlasImages() +void VkLightmap::CreateAtlasImages(const TArray& surfaceIndices) { + for (auto& page : atlasImages) + { + page.pageMaxX = 0; + page.pageMaxY = 0; + } + const int spacing = 3; // Note: the spacing is here to avoid that the resolve sampler finds data from other surface tiles RectPacker packer(atlasImageSize, atlasImageSize, RectPacker::Spacing(spacing)); - for (int i = 0, count = mesh->GetSurfaceCount(); i < count; i++) + size_t pageIndex = atlasImages.size(); + + for (int i = 0, count = surfaceIndices.Size(); i < count; i++) { - LevelMeshSurface* surface = mesh->GetSurface(i); + LevelMeshSurface* surface = mesh->GetSurface(surfaceIndices[i]); + //for (int i = 0, count = mesh->GetSurfaceCount(); i < count; i++) + //{ + //LevelMeshSurface* surface = mesh->GetSurface(i); auto result = packer.insert(surface->texWidth + 2, surface->texHeight + 2); surface->lightmapperAtlasX = result.pos.x + 1; surface->lightmapperAtlasY = result.pos.y + 1; surface->lightmapperAtlasPage = (int)result.pageIndex; - } - for (size_t pageIndex = atlasImages.size(); pageIndex < packer.getNumPages(); pageIndex++) - { - atlasImages.push_back(CreateImage(atlasImageSize, atlasImageSize)); + for (;pageIndex <= result.pageIndex; pageIndex++) + { + atlasImages.push_back(CreateImage(atlasImageSize, atlasImageSize)); + } + + auto& image = atlasImages[result.pageIndex]; + image.pageMaxX = std::max(image.pageMaxX, uint16_t(surface->lightmapperAtlasX + surface->texWidth + spacing)); + image.pageMaxY = std::max(image.pageMaxY, uint16_t(surface->lightmapperAtlasY + surface->texHeight + spacing)); } } @@ -297,7 +325,7 @@ void VkLightmap::ResolveAtlasImage(size_t pageIndex) RenderPassBegin() .RenderPass(resolve.renderPass.get()) - .RenderArea(0, 0, atlasImageSize, atlasImageSize) + .RenderArea(0, 0, img.pageMaxX, img.pageMaxY) .Framebuffer(img.resolve.Framebuffer.get()) .Execute(cmdbuffer); @@ -308,8 +336,8 @@ void VkLightmap::ResolveAtlasImage(size_t pageIndex) VkViewport viewport = {}; viewport.maxDepth = 1; - viewport.width = (float)atlasImageSize; - viewport.height = (float)atlasImageSize; + viewport.width = (float)img.pageMaxX; + viewport.height = (float)img.pageMaxY; cmdbuffer->setViewport(0, 1, &viewport); LightmapPushConstants pc; @@ -348,7 +376,7 @@ void VkLightmap::BlurAtlasImage(size_t pageIndex) { RenderPassBegin() .RenderPass(blur.renderPass.get()) - .RenderArea(0, 0, atlasImageSize, atlasImageSize) + .RenderArea(0, 0, img.pageMaxX, img.pageMaxY) .Framebuffer(img.blur.Framebuffer.get()) .Execute(cmdbuffer); @@ -359,8 +387,8 @@ void VkLightmap::BlurAtlasImage(size_t pageIndex) VkViewport viewport = {}; viewport.maxDepth = 1; - viewport.width = (float)atlasImageSize; - viewport.height = (float)atlasImageSize; + viewport.width = (float)img.pageMaxX; + viewport.height = (float)img.pageMaxY; cmdbuffer->setViewport(0, 1, &viewport); LightmapPushConstants pc; @@ -393,7 +421,7 @@ void VkLightmap::BlurAtlasImage(size_t pageIndex) { RenderPassBegin() .RenderPass(blur.renderPass.get()) - .RenderArea(0, 0, atlasImageSize, atlasImageSize) + .RenderArea(0, 0, img.pageMaxX, img.pageMaxY) .Framebuffer(img.resolve.Framebuffer.get()) .Execute(cmdbuffer); @@ -404,8 +432,8 @@ void VkLightmap::BlurAtlasImage(size_t pageIndex) VkViewport viewport = {}; viewport.maxDepth = 1; - viewport.width = (float)atlasImageSize; - viewport.height = (float)atlasImageSize; + viewport.width = (float)img.pageMaxX; + viewport.height = (float)img.pageMaxY; cmdbuffer->setViewport(0, 1, &viewport); LightmapPushConstants pc; diff --git a/src/common/rendering/vulkan/accelstructs/vk_lightmap.h b/src/common/rendering/vulkan/accelstructs/vk_lightmap.h index 709fa75f4c..bce8d0c72b 100644 --- a/src/common/rendering/vulkan/accelstructs/vk_lightmap.h +++ b/src/common/rendering/vulkan/accelstructs/vk_lightmap.h @@ -55,6 +55,10 @@ struct LightmapImage std::unique_ptr Framebuffer; std::unique_ptr DescriptorSet[2]; } blur; + + // how much of the page is used? + uint16_t pageMaxX = 0; + uint16_t pageMaxY = 0; }; struct SceneVertex @@ -92,7 +96,7 @@ private: void UpdateAccelStructDescriptors(); void UploadUniforms(); - void CreateAtlasImages(); + void CreateAtlasImages(const TArray& surfaceIndices); void RenderAtlasImage(size_t pageIndex, const TArray& surfaceIndices); void ResolveAtlasImage(size_t pageIndex); void BlurAtlasImage(size_t pageIndex); diff --git a/src/rendering/hwrenderer/hw_entrypoint.cpp b/src/rendering/hwrenderer/hw_entrypoint.cpp index 9e7b09724b..948e4a1a66 100644 --- a/src/rendering/hwrenderer/hw_entrypoint.cpp +++ b/src/rendering/hwrenderer/hw_entrypoint.cpp @@ -51,6 +51,7 @@ #include "hwrenderer/scene/hw_drawcontext.h" #include "hw_vrmodes.h" +EXTERN_CVAR(Int, lm_background_updates); EXTERN_CVAR(Bool, cl_capfps) extern bool NoInterpolateView; @@ -198,7 +199,24 @@ sector_t* RenderViewpoint(FRenderViewpoint& mainvp, AActor* camera, IntRect* bou screen->NextEye(eyeCount); } - screen->UpdateLightmaps(RenderState.GetVisibleSurfaceList()); + auto& list = RenderState.GetVisibleSurfaceList(); + if (list.Size() <= lm_background_updates) + { + int index = 0; + for (auto& e : level.levelMesh->Surfaces) + { + if (e.needsUpdate) + { + list.Push(index); + + if(list.Size() >= lm_background_updates) + break; + } + ++index; + } + } + + screen->UpdateLightmaps(list); return mainvp.sector; }