mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-29 07:12:36 +00:00
Update lightmapper and add limiter to updates
This commit is contained in:
parent
acc50ef36e
commit
995de6f71d
4 changed files with 88 additions and 36 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue