Fix Global Surface Atlas defragmentation flicker when atlas it nearly full
This commit is contained in:
@@ -79,10 +79,7 @@ struct GlobalSurfaceAtlasTile : RectPack<GlobalSurfaceAtlasTile, uint16>
|
|||||||
}
|
}
|
||||||
|
|
||||||
void OnInsert(class GlobalSurfaceAtlasCustomBuffer* buffer, void* actorObject, int32 tileIndex);
|
void OnInsert(class GlobalSurfaceAtlasCustomBuffer* buffer, void* actorObject, int32 tileIndex);
|
||||||
|
void OnFree(GlobalSurfaceAtlasCustomBuffer* buffer);
|
||||||
void OnFree()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GlobalSurfaceAtlasObject
|
struct GlobalSurfaceAtlasObject
|
||||||
@@ -135,6 +132,7 @@ public:
|
|||||||
int32 Resolution = 0;
|
int32 Resolution = 0;
|
||||||
uint64 LastFrameAtlasInsertFail = 0;
|
uint64 LastFrameAtlasInsertFail = 0;
|
||||||
uint64 LastFrameAtlasDefragmentation = 0;
|
uint64 LastFrameAtlasDefragmentation = 0;
|
||||||
|
int32 AtlasPixelsUsed = 0;
|
||||||
GPUTexture* AtlasDepth = nullptr;
|
GPUTexture* AtlasDepth = nullptr;
|
||||||
GPUTexture* AtlasEmissive = nullptr;
|
GPUTexture* AtlasEmissive = nullptr;
|
||||||
GPUTexture* AtlasGBuffer0 = nullptr;
|
GPUTexture* AtlasGBuffer0 = nullptr;
|
||||||
@@ -170,6 +168,7 @@ public:
|
|||||||
CulledObjectsCounterIndex = -1;
|
CulledObjectsCounterIndex = -1;
|
||||||
CulledObjectsUsageHistory.Clear();
|
CulledObjectsUsageHistory.Clear();
|
||||||
LastFrameAtlasDefragmentation = Engine::FrameCount;
|
LastFrameAtlasDefragmentation = Engine::FrameCount;
|
||||||
|
AtlasPixelsUsed = 0;
|
||||||
SAFE_DELETE(AtlasTiles);
|
SAFE_DELETE(AtlasTiles);
|
||||||
Objects.Clear();
|
Objects.Clear();
|
||||||
Lights.Clear();
|
Lights.Clear();
|
||||||
@@ -230,6 +229,12 @@ public:
|
|||||||
void GlobalSurfaceAtlasTile::OnInsert(GlobalSurfaceAtlasCustomBuffer* buffer, void* actorObject, int32 tileIndex)
|
void GlobalSurfaceAtlasTile::OnInsert(GlobalSurfaceAtlasCustomBuffer* buffer, void* actorObject, int32 tileIndex)
|
||||||
{
|
{
|
||||||
buffer->Objects[actorObject].Tiles[tileIndex] = this;
|
buffer->Objects[actorObject].Tiles[tileIndex] = this;
|
||||||
|
buffer->AtlasPixelsUsed += (int32)Width * (int32)Height;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GlobalSurfaceAtlasTile::OnFree(GlobalSurfaceAtlasCustomBuffer* buffer)
|
||||||
|
{
|
||||||
|
buffer->AtlasPixelsUsed -= (int32)Width * (int32)Height;
|
||||||
}
|
}
|
||||||
|
|
||||||
String GlobalSurfaceAtlasPass::ToString() const
|
String GlobalSurfaceAtlasPass::ToString() const
|
||||||
@@ -422,9 +427,10 @@ bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* co
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Perform atlas defragmentation if needed
|
// Perform atlas defragmentation if needed
|
||||||
// TODO: track atlas used vs free ratio to skip defragmentation if it's nearly full (then maybe auto resize up?)
|
constexpr float maxUsageToDefrag = 0.8f;
|
||||||
if (currentFrame - surfaceAtlasData.LastFrameAtlasInsertFail < 10 &&
|
if (currentFrame - surfaceAtlasData.LastFrameAtlasInsertFail < 10 &&
|
||||||
currentFrame - surfaceAtlasData.LastFrameAtlasDefragmentation > 60)
|
currentFrame - surfaceAtlasData.LastFrameAtlasDefragmentation > 60 &&
|
||||||
|
(float)surfaceAtlasData.AtlasPixelsUsed / (resolution * resolution) < maxUsageToDefrag)
|
||||||
{
|
{
|
||||||
surfaceAtlasData.ClearObjects();
|
surfaceAtlasData.ClearObjects();
|
||||||
}
|
}
|
||||||
@@ -516,7 +522,7 @@ bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* co
|
|||||||
for (auto& tile : it->Value.Tiles)
|
for (auto& tile : it->Value.Tiles)
|
||||||
{
|
{
|
||||||
if (tile)
|
if (tile)
|
||||||
tile->Free();
|
tile->Free(&surfaceAtlasData);
|
||||||
}
|
}
|
||||||
surfaceAtlasData.Objects.Remove(it);
|
surfaceAtlasData.Objects.Remove(it);
|
||||||
}
|
}
|
||||||
@@ -1217,7 +1223,7 @@ void GlobalSurfaceAtlasPass::RasterizeActor(Actor* actor, void* actorObject, con
|
|||||||
// Skip too small surfaces
|
// Skip too small surfaces
|
||||||
if (object && object->Tiles[tileIndex])
|
if (object && object->Tiles[tileIndex])
|
||||||
{
|
{
|
||||||
object->Tiles[tileIndex]->Free();
|
object->Tiles[tileIndex]->Free(&surfaceAtlasData);
|
||||||
object->Tiles[tileIndex] = nullptr;
|
object->Tiles[tileIndex] = nullptr;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
@@ -1240,7 +1246,7 @@ void GlobalSurfaceAtlasPass::RasterizeActor(Actor* actor, void* actorObject, con
|
|||||||
anyTile = true;
|
anyTile = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
object->Tiles[tileIndex]->Free();
|
object->Tiles[tileIndex]->Free(&surfaceAtlasData);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert tile into atlas
|
// Insert tile into atlas
|
||||||
|
|||||||
Reference in New Issue
Block a user