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_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;
}

View file

@ -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 <set>
#endif
void VkLightmap::Raytrace(LevelMesh* level, const TArray<int>& surfaceIndices)
{
@ -52,7 +58,6 @@ void VkLightmap::Raytrace(LevelMesh* level, const TArray<int>& surfaceIndices)
if (newLevel)
{
UpdateAccelStructDescriptors();
CreateAtlasImages();
lightmapRaytrace.Reset();
lightmapRaytraceLast.Reset();
@ -64,6 +69,8 @@ void VkLightmap::Raytrace(LevelMesh* level, const TArray<int>& surfaceIndices)
lightmapRaytrace.Clock();
lightmapRaytraceLast.ResetAndClock();
CreateAtlasImages(surfaceIndices);
#if 0
TArray<int> allSurfaces;
@ -99,14 +106,20 @@ void VkLightmap::Raytrace(LevelMesh* level, const TArray<int>& 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<int>& surfaceIn
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
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<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));
}
}
@ -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;

View file

@ -55,6 +55,10 @@ struct LightmapImage
std::unique_ptr<VulkanFramebuffer> Framebuffer;
std::unique_ptr<VulkanDescriptorSet> 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<int>& surfaceIndices);
void RenderAtlasImage(size_t pageIndex, const TArray<int>& surfaceIndices);
void ResolveAtlasImage(size_t pageIndex);
void BlurAtlasImage(size_t pageIndex);

View file

@ -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;
}