Update lightmapper and add limiter to updates

This commit is contained in:
RaveYard 2023-09-09 10:11:43 +02:00 committed by Christoph Oelckers
parent acc50ef36e
commit 995de6f71d
4 changed files with 88 additions and 36 deletions

View file

@ -10,6 +10,8 @@
#include "hw_viewpointuniforms.h" #include "hw_viewpointuniforms.h"
#include "hw_cvars.h" #include "hw_cvars.h"
EXTERN_CVAR(Int, lm_max_updates);
struct FColormap; struct FColormap;
class IBuffer; class IBuffer;
struct HWViewpointUniforms; struct HWViewpointUniforms;
@ -733,11 +735,11 @@ public:
inline void PushVisibleSurface(int surfaceIndex, LevelMeshSurface* surface) 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); mActiveLightmapSurfaces.Push(surfaceIndex);
} }
inline const auto& GetVisibleSurfaceList() const inline auto& GetVisibleSurfaceList()
{ {
return mActiveLightmapSurfaces; return mActiveLightmapSurfaces;
} }

View file

@ -9,6 +9,21 @@
#include "filesystem.h" #include "filesystem.h"
#include "cmdlib.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) VkLightmap::VkLightmap(VulkanRenderDevice* fb) : fb(fb)
{ {
useRayQuery = fb->GetDevice()->PhysicalDevice.Features.RayQuery.rayQuery; useRayQuery = fb->GetDevice()->PhysicalDevice.Features.RayQuery.rayQuery;
@ -31,18 +46,9 @@ VkLightmap::~VkLightmap()
lights.Buffer->Unmap(); lights.Buffer->Unmap();
} }
static int lastSurfaceCount; #if 0
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;
}
#include <set> #include <set>
#endif
void VkLightmap::Raytrace(LevelMesh* level, const TArray<int>& surfaceIndices) void VkLightmap::Raytrace(LevelMesh* level, const TArray<int>& surfaceIndices)
{ {
@ -52,7 +58,6 @@ void VkLightmap::Raytrace(LevelMesh* level, const TArray<int>& surfaceIndices)
if (newLevel) if (newLevel)
{ {
UpdateAccelStructDescriptors(); UpdateAccelStructDescriptors();
CreateAtlasImages();
lightmapRaytrace.Reset(); lightmapRaytrace.Reset();
lightmapRaytraceLast.Reset(); lightmapRaytraceLast.Reset();
@ -64,6 +69,8 @@ void VkLightmap::Raytrace(LevelMesh* level, const TArray<int>& surfaceIndices)
lightmapRaytrace.Clock(); lightmapRaytrace.Clock();
lightmapRaytraceLast.ResetAndClock(); lightmapRaytraceLast.ResetAndClock();
CreateAtlasImages(surfaceIndices);
#if 0 #if 0
TArray<int> allSurfaces; TArray<int> allSurfaces;
@ -98,16 +105,22 @@ void VkLightmap::Raytrace(LevelMesh* level, const TArray<int>& surfaceIndices)
lastSurfaceCount = allSurfaces.Size(); lastSurfaceCount = allSurfaces.Size();
for (size_t pageIndex = 0; pageIndex < atlasImages.size(); pageIndex++) for (size_t pageIndex = 0; pageIndex < atlasImages.size(); pageIndex++)
{
if (atlasImages[pageIndex].pageMaxX && atlasImages[pageIndex].pageMaxY)
{ {
RenderAtlasImage(pageIndex, allSurfaces); RenderAtlasImage(pageIndex, allSurfaces);
} }
}
for (size_t pageIndex = 0; pageIndex < atlasImages.size(); pageIndex++) for (size_t pageIndex = 0; pageIndex < atlasImages.size(); pageIndex++)
{
if (atlasImages[pageIndex].pageMaxX && atlasImages[pageIndex].pageMaxY)
{ {
ResolveAtlasImage(pageIndex); ResolveAtlasImage(pageIndex);
BlurAtlasImage(pageIndex); BlurAtlasImage(pageIndex);
CopyAtlasImageResult(pageIndex, allSurfaces); CopyAtlasImageResult(pageIndex, allSurfaces);
} }
}
lightmapRaytrace.Unclock(); lightmapRaytrace.Unclock();
lightmapRaytraceLast.Unclock(); lightmapRaytraceLast.Unclock();
@ -246,25 +259,40 @@ void VkLightmap::RenderAtlasImage(size_t pageIndex, const TArray<int>& surfaceIn
fb->GetCommands()->GetTransferCommands()->endRenderPass(); fb->GetCommands()->GetTransferCommands()->endRenderPass();
} }
void VkLightmap::CreateAtlasImages() void VkLightmap::CreateAtlasImages(const TArray<int>& 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 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)); 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); auto result = packer.insert(surface->texWidth + 2, surface->texHeight + 2);
surface->lightmapperAtlasX = result.pos.x + 1; surface->lightmapperAtlasX = result.pos.x + 1;
surface->lightmapperAtlasY = result.pos.y + 1; surface->lightmapperAtlasY = result.pos.y + 1;
surface->lightmapperAtlasPage = (int)result.pageIndex; surface->lightmapperAtlasPage = (int)result.pageIndex;
}
for (size_t pageIndex = atlasImages.size(); pageIndex < packer.getNumPages(); pageIndex++) for (;pageIndex <= result.pageIndex; pageIndex++)
{ {
atlasImages.push_back(CreateImage(atlasImageSize, atlasImageSize)); atlasImages.push_back(CreateImage(atlasImageSize, atlasImageSize));
} }
auto& image = atlasImages[result.pageIndex];
image.pageMaxX = std::max<uint16_t>(image.pageMaxX, uint16_t(surface->lightmapperAtlasX + surface->texWidth + spacing));
image.pageMaxY = std::max<uint16_t>(image.pageMaxY, uint16_t(surface->lightmapperAtlasY + surface->texHeight + spacing));
}
} }
void VkLightmap::UploadUniforms() void VkLightmap::UploadUniforms()
@ -297,7 +325,7 @@ void VkLightmap::ResolveAtlasImage(size_t pageIndex)
RenderPassBegin() RenderPassBegin()
.RenderPass(resolve.renderPass.get()) .RenderPass(resolve.renderPass.get())
.RenderArea(0, 0, atlasImageSize, atlasImageSize) .RenderArea(0, 0, img.pageMaxX, img.pageMaxY)
.Framebuffer(img.resolve.Framebuffer.get()) .Framebuffer(img.resolve.Framebuffer.get())
.Execute(cmdbuffer); .Execute(cmdbuffer);
@ -308,8 +336,8 @@ void VkLightmap::ResolveAtlasImage(size_t pageIndex)
VkViewport viewport = {}; VkViewport viewport = {};
viewport.maxDepth = 1; viewport.maxDepth = 1;
viewport.width = (float)atlasImageSize; viewport.width = (float)img.pageMaxX;
viewport.height = (float)atlasImageSize; viewport.height = (float)img.pageMaxY;
cmdbuffer->setViewport(0, 1, &viewport); cmdbuffer->setViewport(0, 1, &viewport);
LightmapPushConstants pc; LightmapPushConstants pc;
@ -348,7 +376,7 @@ void VkLightmap::BlurAtlasImage(size_t pageIndex)
{ {
RenderPassBegin() RenderPassBegin()
.RenderPass(blur.renderPass.get()) .RenderPass(blur.renderPass.get())
.RenderArea(0, 0, atlasImageSize, atlasImageSize) .RenderArea(0, 0, img.pageMaxX, img.pageMaxY)
.Framebuffer(img.blur.Framebuffer.get()) .Framebuffer(img.blur.Framebuffer.get())
.Execute(cmdbuffer); .Execute(cmdbuffer);
@ -359,8 +387,8 @@ void VkLightmap::BlurAtlasImage(size_t pageIndex)
VkViewport viewport = {}; VkViewport viewport = {};
viewport.maxDepth = 1; viewport.maxDepth = 1;
viewport.width = (float)atlasImageSize; viewport.width = (float)img.pageMaxX;
viewport.height = (float)atlasImageSize; viewport.height = (float)img.pageMaxY;
cmdbuffer->setViewport(0, 1, &viewport); cmdbuffer->setViewport(0, 1, &viewport);
LightmapPushConstants pc; LightmapPushConstants pc;
@ -393,7 +421,7 @@ void VkLightmap::BlurAtlasImage(size_t pageIndex)
{ {
RenderPassBegin() RenderPassBegin()
.RenderPass(blur.renderPass.get()) .RenderPass(blur.renderPass.get())
.RenderArea(0, 0, atlasImageSize, atlasImageSize) .RenderArea(0, 0, img.pageMaxX, img.pageMaxY)
.Framebuffer(img.resolve.Framebuffer.get()) .Framebuffer(img.resolve.Framebuffer.get())
.Execute(cmdbuffer); .Execute(cmdbuffer);
@ -404,8 +432,8 @@ void VkLightmap::BlurAtlasImage(size_t pageIndex)
VkViewport viewport = {}; VkViewport viewport = {};
viewport.maxDepth = 1; viewport.maxDepth = 1;
viewport.width = (float)atlasImageSize; viewport.width = (float)img.pageMaxX;
viewport.height = (float)atlasImageSize; viewport.height = (float)img.pageMaxY;
cmdbuffer->setViewport(0, 1, &viewport); cmdbuffer->setViewport(0, 1, &viewport);
LightmapPushConstants pc; LightmapPushConstants pc;

View file

@ -55,6 +55,10 @@ struct LightmapImage
std::unique_ptr<VulkanFramebuffer> Framebuffer; std::unique_ptr<VulkanFramebuffer> Framebuffer;
std::unique_ptr<VulkanDescriptorSet> DescriptorSet[2]; std::unique_ptr<VulkanDescriptorSet> DescriptorSet[2];
} blur; } blur;
// how much of the page is used?
uint16_t pageMaxX = 0;
uint16_t pageMaxY = 0;
}; };
struct SceneVertex struct SceneVertex
@ -92,7 +96,7 @@ private:
void UpdateAccelStructDescriptors(); void UpdateAccelStructDescriptors();
void UploadUniforms(); void UploadUniforms();
void CreateAtlasImages(); void CreateAtlasImages(const TArray<int>& surfaceIndices);
void RenderAtlasImage(size_t pageIndex, const TArray<int>& surfaceIndices); void RenderAtlasImage(size_t pageIndex, const TArray<int>& surfaceIndices);
void ResolveAtlasImage(size_t pageIndex); void ResolveAtlasImage(size_t pageIndex);
void BlurAtlasImage(size_t pageIndex); void BlurAtlasImage(size_t pageIndex);

View file

@ -51,6 +51,7 @@
#include "hwrenderer/scene/hw_drawcontext.h" #include "hwrenderer/scene/hw_drawcontext.h"
#include "hw_vrmodes.h" #include "hw_vrmodes.h"
EXTERN_CVAR(Int, lm_background_updates);
EXTERN_CVAR(Bool, cl_capfps) EXTERN_CVAR(Bool, cl_capfps)
extern bool NoInterpolateView; extern bool NoInterpolateView;
@ -198,7 +199,24 @@ sector_t* RenderViewpoint(FRenderViewpoint& mainvp, AActor* camera, IntRect* bou
screen->NextEye(eyeCount); 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; return mainvp.sector;
} }