Clean up the ranges code a bit

This commit is contained in:
Magnus Norddahl 2024-12-16 22:17:18 +01:00
commit e30831a409
7 changed files with 403 additions and 227 deletions

View file

@ -90,14 +90,14 @@ extern glcycle_t DynamicBLASTime;
void CPUAccelStruct::Update()
{
if (Mesh->UploadRanges.Index.Size() == 0)
if (Mesh->UploadRanges.Index.GetRanges().Size() == 0)
return;
DynamicBLASTime.ResetAndClock();
InstanceCount = (Mesh->Mesh.IndexCount + IndexesPerBLAS - 1) / IndexesPerBLAS;
std::vector<bool> needsUpdate(InstanceCount);
for (const MeshBufferRange& range : Mesh->UploadRanges.Index)
for (const MeshBufferRange& range : Mesh->UploadRanges.Index.GetRanges())
{
int start = range.Start / IndexesPerBLAS;
int end = range.End / IndexesPerBLAS;
@ -214,7 +214,7 @@ void CPUAccelStruct::Upload()
}
Mesh->UploadRanges.Node.Clear();
Mesh->UploadRanges.Node.Push({ 0, (int)count });
Mesh->UploadRanges.Node.Add(0, (int)count);
}
void CPUAccelStruct::CreateTLAS()

View file

@ -46,13 +46,13 @@ void LevelMesh::Reset(const LevelMeshLimits& limits)
Mesh.DrawIndexes.Resize(limits.MaxIndexes);
FreeLists.Vertex.Clear(); FreeLists.Vertex.Push({ 0, limits.MaxVertices });
FreeLists.Index.Clear(); FreeLists.Index.Push({ 0, limits.MaxIndexes });
FreeLists.Uniforms.Clear(); FreeLists.Uniforms.Push({ 0, limits.MaxUniforms });
FreeLists.Surface.Clear(); FreeLists.Surface.Push({ 0, limits.MaxSurfaces });
FreeLists.DrawIndex.Clear(); FreeLists.DrawIndex.Push({ 0, limits.MaxIndexes });
FreeLists.LightIndex.Clear(); FreeLists.LightIndex.Push({ 0, limits.MaxSurfaces * 10 });
FreeLists.Light.Clear(); FreeLists.Light.Push({ 0, maxLights });
FreeLists.Vertex.Reset(limits.MaxVertices);
FreeLists.Index.Reset(limits.MaxIndexes);
FreeLists.Uniforms.Reset(limits.MaxUniforms);
FreeLists.Surface.Reset(limits.MaxSurfaces);
FreeLists.DrawIndex.Reset(limits.MaxIndexes);
FreeLists.LightIndex.Reset(limits.MaxSurfaces * 10);
FreeLists.Light.Reset(maxLights);
}
void LevelMesh::AddEmptyMesh()
@ -246,3 +246,264 @@ void LevelMesh::PackDynamicLightmapAtlas()
}
}
}
/////////////////////////////////////////////////////////////////////////////
void MeshBufferAllocator::Reset(int size)
{
TotalSize = size;
Unused.Clear();
Unused.Push({ 0, size });
}
int MeshBufferAllocator::GetTotalSize() const
{
return TotalSize;
}
int MeshBufferAllocator::GetUsedSize() const
{
int used = TotalSize;
for (auto& range : Unused)
{
int count = range.End - range.Start;
used -= count;
}
return used;
}
int MeshBufferAllocator::Alloc(int count)
{
for (unsigned int i = 0, size = Unused.Size(); i < size; i++)
{
auto& item = Unused[i];
if (item.End - item.Start >= count)
{
int pos = item.Start;
item.Start += count;
if (item.Start == item.End)
{
Unused.Delete(i);
}
return pos;
}
}
I_FatalError("Could not find space in level mesh buffer");
}
void MeshBufferAllocator::Free(int position, int count)
{
if (count <= 0)
return;
MeshBufferRange range = { position, position + count };
// First element?
if (Unused.Size() == 0)
{
Unused.push_back(range);
return;
}
// Find start position in ranges
auto right = std::lower_bound(Unused.begin(), Unused.end(), range, [](const auto& a, const auto& b) { return a.Start < b.Start; });
bool leftExists = right != Unused.begin();
bool rightExists = right != Unused.end();
auto left = right;
if (leftExists)
--left;
// Is this a gap between two ranges?
if ((!leftExists || left->End < range.Start) && (!rightExists || right->Start > range.End))
{
Unused.Insert(right - Unused.begin(), range);
return;
}
// Are we extending the left or the right range?
if (leftExists && range.Start <= left->End)
{
left->End = std::max(left->End, range.End);
right = left;
}
else // if (rightExists && right->Start <= range.End)
{
right->Start = range.Start;
right->End = std::max(right->End, range.End);
left = right;
}
// Merge overlaps to the right
while (true)
{
++right;
if (right == Unused.end() || right->Start > range.End)
break;
left->End = std::max(right->End, range.End);
}
// Remove ranges now covered by the extended range
//Unused.erase(++left, right);
++left;
auto leftPos = left - Unused.begin();
auto rightPos = right - Unused.begin();
Unused.Delete(leftPos, rightPos - leftPos);
}
/////////////////////////////////////////////////////////////////////////////
void MeshBufferUploads::Clear()
{
Ranges.Clear();
}
void MeshBufferUploads::Add(int position, int count)
{
if (count <= 0)
return;
MeshBufferRange range = { position, position + count };
// First element?
if (Ranges.Size() == 0)
{
Ranges.push_back(range);
return;
}
// Find start position in ranges
auto right = std::lower_bound(Ranges.begin(), Ranges.end(), range, [](const auto& a, const auto& b) { return a.Start < b.Start; });
bool leftExists = right != Ranges.begin();
bool rightExists = right != Ranges.end();
auto left = right;
if (leftExists)
--left;
// Is this a gap between two ranges?
if ((!leftExists || left->End < range.Start) && (!rightExists || right->Start > range.End))
{
Ranges.Insert(right - Ranges.begin(), range);
return;
}
// Are we extending the left or the right range?
if (leftExists && range.Start <= left->End)
{
left->End = std::max(left->End, range.End);
right = left;
}
else // if (rightExists && right->Start <= range.End)
{
right->Start = range.Start;
right->End = std::max(right->End, range.End);
left = right;
}
// Merge overlaps to the right
while (true)
{
++right;
if (right == Ranges.end() || right->Start > range.End)
break;
left->End = std::max(right->End, range.End);
}
// Remove ranges now covered by the extended range
//ranges.erase(++left, right);
++left;
auto leftPos = left - Ranges.begin();
auto rightPos = right - Ranges.begin();
Ranges.Delete(leftPos, rightPos - leftPos);
}
/////////////////////////////////////////////////////////////////////////////
void LevelMeshDrawList::Add(int position, int count)
{
if (count <= 0)
return;
MeshBufferRange range = { position, position + count };
// First element?
if (Ranges.Size() == 0)
{
Ranges.push_back(range);
return;
}
// Find start position in ranges
auto right = std::lower_bound(Ranges.begin(), Ranges.end(), range, [](const auto& a, const auto& b) { return a.Start < b.Start; });
bool leftExists = right != Ranges.begin();
bool rightExists = right != Ranges.end();
auto left = right;
if (leftExists)
--left;
// Is this a gap between two ranges?
if ((!leftExists || left->End < range.Start) && (!rightExists || right->Start > range.End))
{
Ranges.Insert(right - Ranges.begin(), range);
return;
}
// Are we extending the left or the right range?
if (leftExists && range.Start <= left->End)
{
left->End = std::max(left->End, range.End);
right = left;
}
else // if (rightExists && right->Start <= range.End)
{
right->Start = range.Start;
right->End = std::max(right->End, range.End);
left = right;
}
// Merge overlaps to the right
while (true)
{
++right;
if (right == Ranges.end() || right->Start > range.End)
break;
left->End = std::max(right->End, range.End);
}
// Remove ranges now covered by the extended range
//ranges.erase(++left, right);
++left;
auto leftPos = left - Ranges.begin();
auto rightPos = right - Ranges.begin();
Ranges.Delete(leftPos, rightPos - leftPos);
}
void LevelMeshDrawList::Remove(int position, int count)
{
if (count <= 0)
return;
MeshBufferRange range = { position, position + count };
auto entry = std::lower_bound(Ranges.begin(), Ranges.end(), range, [](const auto& a, const auto& b) { return a.End < b.End; });
if (entry->Start == range.Start && entry->End == range.End)
{
Ranges.Delete(entry - Ranges.begin());
}
else if (entry->Start == range.Start)
{
entry->Start = range.End;
}
else if (entry->End == range.End)
{
entry->End = range.Start;
}
else
{
MeshBufferRange split;
split.Start = entry->Start;
split.End = range.Start;
entry->Start = range.End;
Ranges.Insert(entry - Ranges.begin(), split);
}
}

View file

@ -67,6 +67,44 @@ struct MeshBufferRange
int Count() const { return End - Start; }
};
class MeshBufferAllocator
{
public:
void Reset(int size);
int GetTotalSize() const;
int GetUsedSize() const;
int Alloc(int count);
void Free(int position, int count);
private:
int TotalSize = 0;
TArray<MeshBufferRange> Unused;
};
class MeshBufferUploads
{
public:
void Clear();
void Add(int position, int count);
const TArray<MeshBufferRange>& GetRanges() const { return Ranges; }
private:
TArray<MeshBufferRange> Ranges;
};
class LevelMeshDrawList
{
public:
void Add(int position, int count);
void Remove(int position, int count);
const TArray<MeshBufferRange>& GetRanges() const { return Ranges; }
private:
TArray<MeshBufferRange> Ranges;
};
struct LevelMeshLimits
{
int MaxVertices = 0;
@ -150,38 +188,38 @@ public:
// Ranges in mesh that have changed since last upload
struct
{
TArray<MeshBufferRange> Vertex;
TArray<MeshBufferRange> Index;
TArray<MeshBufferRange> Node;
TArray<MeshBufferRange> SurfaceIndex;
TArray<MeshBufferRange> Surface;
TArray<MeshBufferRange> UniformIndexes;
TArray<MeshBufferRange> Uniforms;
TArray<MeshBufferRange> LightUniforms;
TArray<MeshBufferRange> Portals;
TArray<MeshBufferRange> Light;
TArray<MeshBufferRange> LightIndex;
TArray<MeshBufferRange> DynLight;
TArray<MeshBufferRange> DrawIndex;
MeshBufferUploads Vertex;
MeshBufferUploads Index;
MeshBufferUploads Node;
MeshBufferUploads SurfaceIndex;
MeshBufferUploads Surface;
MeshBufferUploads UniformIndexes;
MeshBufferUploads Uniforms;
MeshBufferUploads LightUniforms;
MeshBufferUploads Portals;
MeshBufferUploads Light;
MeshBufferUploads LightIndex;
MeshBufferUploads DynLight;
MeshBufferUploads DrawIndex;
} UploadRanges;
// Ranges in mesh currently not in use
struct
{
TArray<MeshBufferRange> Vertex;
TArray<MeshBufferRange> Index;
TArray<MeshBufferRange> Uniforms;
TArray<MeshBufferRange> Surface;
TArray<MeshBufferRange> Light;
TArray<MeshBufferRange> LightIndex;
TArray<MeshBufferRange> DrawIndex;
MeshBufferAllocator Vertex;
MeshBufferAllocator Index;
MeshBufferAllocator Uniforms;
MeshBufferAllocator Surface;
MeshBufferAllocator Light;
MeshBufferAllocator LightIndex;
MeshBufferAllocator DrawIndex;
} FreeLists;
// Data structure for doing mesh traces on the CPU
std::unique_ptr<CPUAccelStruct> Collision;
// Draw index ranges for rendering the level mesh, grouped by pipeline
std::unordered_map<int, TArray<MeshBufferRange>> DrawList[(int)LevelMeshDrawType::NumDrawTypes];
std::unordered_map<int, LevelMeshDrawList> DrawList[(int)LevelMeshDrawType::NumDrawTypes];
// Lightmap tiles and their locations in the texture atlas
struct
@ -205,10 +243,6 @@ public:
void UploadPortals();
void CreateCollision();
void AddRange(TArray<MeshBufferRange>& ranges, MeshBufferRange range);
void RemoveRange(TArray<MeshBufferRange>& ranges, MeshBufferRange range);
int RemoveRange(TArray<MeshBufferRange>& ranges, int count);
};
struct LevelMeshTileStats
@ -224,22 +258,20 @@ struct LevelMeshTileStats
inline GeometryAllocInfo LevelMesh::AllocGeometry(int vertexCount, int indexCount)
{
GeometryAllocInfo info;
info.VertexStart = RemoveRange(FreeLists.Vertex, vertexCount);
info.VertexStart = FreeLists.Vertex.Alloc(vertexCount);
info.VertexCount = vertexCount;
info.IndexStart = RemoveRange(FreeLists.Index, indexCount);
info.IndexStart = FreeLists.Index.Alloc(indexCount);
info.IndexCount = indexCount;
info.Vertices = &Mesh.Vertices[info.VertexStart];
info.UniformIndexes = &Mesh.UniformIndexes[info.VertexStart];
info.Indexes = &Mesh.Indexes[info.IndexStart];
AddRange(UploadRanges.Vertex, { info.VertexStart, info.VertexStart + info.VertexCount });
AddRange(UploadRanges.UniformIndexes, { info.VertexStart, info.VertexStart + info.VertexCount });
AddRange(UploadRanges.Index, { info.IndexStart, info.IndexStart + info.IndexCount });
AddRange(UploadRanges.SurfaceIndex, { info.IndexStart / 3, (info.IndexStart + info.IndexCount) / 3 });
UploadRanges.Vertex.Add(info.VertexStart, info.VertexCount);
UploadRanges.UniformIndexes.Add(info.VertexStart, info.VertexCount);
UploadRanges.Index.Add(info.IndexStart, info.IndexCount);
UploadRanges.SurfaceIndex.Add(info.IndexStart / 3, info.IndexCount);
Mesh.IndexCount = std::max(Mesh.IndexCount, info.IndexStart + info.IndexCount);
if (Mesh.IndexCount > 400000)
Mesh.IndexCount++;
return info;
}
@ -247,14 +279,14 @@ inline GeometryAllocInfo LevelMesh::AllocGeometry(int vertexCount, int indexCoun
inline UniformsAllocInfo LevelMesh::AllocUniforms(int count)
{
UniformsAllocInfo info;
info.Start = RemoveRange(FreeLists.Uniforms, count);
info.Start = FreeLists.Uniforms.Alloc(count);
info.Count = count;
info.Uniforms = &Mesh.Uniforms[info.Start];
info.LightUniforms = &Mesh.LightUniforms[info.Start];
info.Materials = &Mesh.Materials[info.Start];
AddRange(UploadRanges.Uniforms, { info.Start, info.Start + info.Count });
AddRange(UploadRanges.LightUniforms, { info.Start, info.Start + info.Count });
UploadRanges.Uniforms.Add(info.Start, info.Count);
UploadRanges.LightUniforms.Add(info.Start, info.Count);
return info;
}
@ -262,30 +294,28 @@ inline UniformsAllocInfo LevelMesh::AllocUniforms(int count)
inline LightListAllocInfo LevelMesh::AllocLightList(int count)
{
LightListAllocInfo info;
info.Start = RemoveRange(FreeLists.LightIndex, count);
info.Start = FreeLists.LightIndex.Alloc(count);
info.Count = count;
info.List = &Mesh.LightIndexes[info.Start];
AddRange(UploadRanges.LightIndex, { info.Start, info.Start + info.Count });
UploadRanges.LightIndex.Add(info.Start, info.Count);
return info;
}
inline LightAllocInfo LevelMesh::AllocLight()
{
LightAllocInfo info;
info.Index = RemoveRange(FreeLists.Light, 1);
info.Index = FreeLists.Light.Alloc(1);
info.Light = &Mesh.Lights[info.Index];
AddRange(UploadRanges.Light, { info.Index, info.Index + 1 });
UploadRanges.Light.Add(info.Index, 1);
return info;
}
inline SurfaceAllocInfo LevelMesh::AllocSurface()
{
SurfaceAllocInfo info;
info.Index = RemoveRange(FreeLists.Surface, 1);
info.Index = FreeLists.Surface.Alloc(1);
info.Surface = &Mesh.Surfaces[info.Index];
AddRange(UploadRanges.Surface, { info.Index, info.Index + 1 });
UploadRanges.Surface.Add(info.Index, 1);
return info;
}
@ -294,135 +324,29 @@ inline void LevelMesh::FreeGeometry(int vertexStart, int vertexCount, int indexS
// Convert triangles to degenerates
for (int i = 0; i < indexCount; i++)
Mesh.Indexes[indexStart + i] = 0;
AddRange(UploadRanges.Index, { indexStart, indexStart + indexCount });
UploadRanges.Index.Add(indexStart, indexCount);
AddRange(FreeLists.Vertex, { vertexStart, vertexStart + vertexCount });
AddRange(FreeLists.Index, { indexStart, indexStart + indexCount });
FreeLists.Vertex.Free(vertexStart, vertexCount);
FreeLists.Index.Free(indexStart, indexCount);
}
inline void LevelMesh::FreeUniforms(int start, int count)
{
AddRange(FreeLists.Uniforms, { start, start + count });
FreeLists.Uniforms.Free(start, count);
}
inline void LevelMesh::FreeLightList(int start, int count)
{
AddRange(FreeLists.LightIndex, { start, start + count });
FreeLists.LightIndex.Free(start, count);
}
inline void LevelMesh::FreeSurface(unsigned int surfaceIndex)
{
AddRange(FreeLists.Surface, { (int)surfaceIndex, (int)surfaceIndex + 1 });
FreeLists.Surface.Free(surfaceIndex, 1);
}
inline void LevelMesh::UploadPortals()
{
UploadRanges.Portals.Clear();
AddRange(UploadRanges.Portals, { 0, (int)Portals.Size() });
}
inline void LevelMesh::AddRange(TArray<MeshBufferRange>& ranges, MeshBufferRange range)
{
// Empty range?
if (range.Start == range.End)
return;
// First element?
if (ranges.Size() == 0)
{
ranges.push_back(range);
return;
}
// Find start position in ranges
auto right = std::lower_bound(ranges.begin(), ranges.end(), range, [](const auto& a, const auto& b) { return a.Start < b.Start; });
bool leftExists = right != ranges.begin();
bool rightExists = right != ranges.end();
auto left = right;
if (leftExists)
--left;
// Is this a gap between two ranges?
if ((!leftExists || left->End < range.Start) && (!rightExists || right->Start > range.End))
{
ranges.Insert(right - ranges.begin(), range);
return;
}
// Are we extending the left or the right range?
if (leftExists && range.Start <= left->End)
{
left->End = std::max(left->End, range.End);
right = left;
}
else // if (rightExists && right->Start <= range.End)
{
right->Start = range.Start;
right->End = std::max(right->End, range.End);
left = right;
}
// Merge overlaps to the right
while (true)
{
++right;
if (right == ranges.end() || right->Start > range.End)
break;
left->End = std::max(right->End, range.End);
}
// Remove ranges now covered by the extended range
//ranges.erase(++left, right);
++left;
auto leftPos = left - ranges.begin();
auto rightPos = right - ranges.begin();
ranges.Delete(leftPos, rightPos - leftPos);
}
inline void LevelMesh::RemoveRange(TArray<MeshBufferRange>& ranges, MeshBufferRange range)
{
if (range.Start == range.End)
return;
auto entry = std::lower_bound(ranges.begin(), ranges.end(), range, [](const auto& a, const auto& b) { return a.End < b.End; });
if (entry->Start == range.Start && entry->End == range.End)
{
ranges.Delete(entry - ranges.begin());
}
else if (entry->Start == range.Start)
{
entry->Start = range.End;
}
else if (entry->End == range.End)
{
entry->End = range.Start;
}
else
{
MeshBufferRange split;
split.Start = entry->Start;
split.End = range.Start;
entry->Start = range.End;
ranges.Insert(entry - ranges.begin(), split);
}
}
inline int LevelMesh::RemoveRange(TArray<MeshBufferRange>& ranges, int count)
{
for (unsigned int i = 0, size = ranges.Size(); i < size; i++)
{
auto& item = ranges[i];
if (item.End - item.Start >= count)
{
int pos = item.Start;
item.Start += count;
if (item.Start == item.End)
{
ranges.Delete(i);
}
return pos;
}
}
I_FatalError("Could not find space in level mesh buffer");
UploadRanges.Portals.Add(0, (int)Portals.Size());
}

View file

@ -134,8 +134,8 @@ void VkLevelMesh::BeginFrame()
{
InstanceCount = (Mesh->Mesh.IndexCount + IndexesPerBLAS - 1) / IndexesPerBLAS;
accelStructNeedsUpdate = Mesh->UploadRanges.Index.Size() != 0;
for (const MeshBufferRange& range : Mesh->UploadRanges.Index)
accelStructNeedsUpdate = Mesh->UploadRanges.Index.GetRanges().Size() != 0;
for (const MeshBufferRange& range : Mesh->UploadRanges.Index.GetRanges())
{
int start = range.Start / IndexesPerBLAS;
int end = (range.End + IndexesPerBLAS - 1) / IndexesPerBLAS;
@ -768,19 +768,19 @@ void VkLevelMeshUploader::Upload()
void VkLevelMeshUploader::ClearRanges()
{
Mesh->Mesh->UploadRanges.Vertex.clear();
Mesh->Mesh->UploadRanges.Index.clear();
Mesh->Mesh->UploadRanges.Node.clear();
Mesh->Mesh->UploadRanges.SurfaceIndex.clear();
Mesh->Mesh->UploadRanges.Surface.clear();
Mesh->Mesh->UploadRanges.UniformIndexes.clear();
Mesh->Mesh->UploadRanges.Uniforms.clear();
Mesh->Mesh->UploadRanges.LightUniforms.clear();
Mesh->Mesh->UploadRanges.Portals.clear();
Mesh->Mesh->UploadRanges.Light.clear();
Mesh->Mesh->UploadRanges.LightIndex.clear();
Mesh->Mesh->UploadRanges.DynLight.clear();
Mesh->Mesh->UploadRanges.DrawIndex.clear();
Mesh->Mesh->UploadRanges.Vertex.Clear();
Mesh->Mesh->UploadRanges.Index.Clear();
Mesh->Mesh->UploadRanges.Node.Clear();
Mesh->Mesh->UploadRanges.SurfaceIndex.Clear();
Mesh->Mesh->UploadRanges.Surface.Clear();
Mesh->Mesh->UploadRanges.UniformIndexes.Clear();
Mesh->Mesh->UploadRanges.Uniforms.Clear();
Mesh->Mesh->UploadRanges.LightUniforms.Clear();
Mesh->Mesh->UploadRanges.Portals.Clear();
Mesh->Mesh->UploadRanges.Light.Clear();
Mesh->Mesh->UploadRanges.LightIndex.Clear();
Mesh->Mesh->UploadRanges.DynLight.Clear();
Mesh->Mesh->UploadRanges.DrawIndex.Clear();
}
void VkLevelMeshUploader::BeginTransfer(size_t transferBufferSize)
@ -808,7 +808,7 @@ static FVector3 SwapYZ(const FVector3& v)
void VkLevelMeshUploader::UploadNodes()
{
if (Mesh->useRayQuery || Mesh->Mesh->UploadRanges.Node.Size() == 0)
if (Mesh->useRayQuery || Mesh->Mesh->UploadRanges.Node.GetRanges().Size() == 0)
return;
// Always update the header struct of the collision storage buffer block if something changed
@ -819,7 +819,7 @@ void VkLevelMeshUploader::UploadNodes()
datapos += sizeof(CollisionNodeBufferHeader);
// Copy collision nodes
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.Node)
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.Node.GetRanges())
{
size_t copysize = range.Count() * sizeof(CollisionNode);
memcpy(data + datapos, Mesh->Mesh->Mesh.Nodes.Data() + range.Start, copysize);
@ -830,9 +830,9 @@ void VkLevelMeshUploader::UploadNodes()
}
template<typename T>
void VkLevelMeshUploader::UploadRanges(const TArray<MeshBufferRange>& ranges, const T* srcbuffer, VulkanBuffer* destbuffer)
void VkLevelMeshUploader::UploadRanges(const MeshBufferUploads& ranges, const T* srcbuffer, VulkanBuffer* destbuffer)
{
for (const MeshBufferRange& range : ranges)
for (const MeshBufferRange& range : ranges.GetRanges())
{
size_t copysize = range.Count() * sizeof(T);
memcpy(data + datapos, srcbuffer + range.Start, copysize);
@ -844,7 +844,7 @@ void VkLevelMeshUploader::UploadRanges(const TArray<MeshBufferRange>& ranges, co
void VkLevelMeshUploader::UploadSurfaces()
{
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.Surface)
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.Surface.GetRanges())
{
SurfaceInfo* surfaces = (SurfaceInfo*)(data + datapos);
for (int j = 0, count = range.Count(); j < count; j++)
@ -880,7 +880,7 @@ void VkLevelMeshUploader::UploadSurfaces()
void VkLevelMeshUploader::UploadUniforms()
{
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.Uniforms)
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.Uniforms.GetRanges())
{
for (int j = 0, count = range.Count(); j < count; j++)
{
@ -911,7 +911,7 @@ void VkLevelMeshUploader::UploadUniforms()
void VkLevelMeshUploader::UploadPortals()
{
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.Portals)
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.Portals.GetRanges())
{
PortalInfo* portals = (PortalInfo*)(data + datapos);
for (int i = 0, count = range.Count(); i < count; i++)
@ -931,7 +931,7 @@ void VkLevelMeshUploader::UploadPortals()
void VkLevelMeshUploader::UploadLights()
{
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.Light)
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.Light.GetRanges())
{
LightInfo* lights = (LightInfo*)(data + datapos);
for (int i = 0, count = range.Count(); i < count; i++)
@ -963,20 +963,20 @@ size_t VkLevelMeshUploader::GetTransferSize()
size_t transferBufferSize = 0;
if (!Mesh->useRayQuery)
{
if (Mesh->Mesh->UploadRanges.Node.Size() > 0) transferBufferSize += sizeof(CollisionNodeBufferHeader);
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.Node) transferBufferSize += range.Count() * sizeof(CollisionNode);
if (Mesh->Mesh->UploadRanges.Node.GetRanges().Size() > 0) transferBufferSize += sizeof(CollisionNodeBufferHeader);
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.Node.GetRanges()) transferBufferSize += range.Count() * sizeof(CollisionNode);
}
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.Vertex) transferBufferSize += range.Count() * sizeof(FFlatVertex);
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.UniformIndexes) transferBufferSize += range.Count() * sizeof(int);
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.Index) transferBufferSize += range.Count() * sizeof(uint32_t);
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.SurfaceIndex) transferBufferSize += range.Count() * sizeof(int);
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.Surface) transferBufferSize += range.Count() * sizeof(SurfaceInfo);
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.Uniforms) transferBufferSize += range.Count() * sizeof(SurfaceUniforms);
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.LightUniforms) transferBufferSize += range.Count() * sizeof(SurfaceLightUniforms);
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.Portals) transferBufferSize += range.Count() * sizeof(PortalInfo);
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.LightIndex) transferBufferSize += range.Count() * sizeof(int32_t);
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.Light) transferBufferSize += range.Count() * sizeof(LightInfo);
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.DynLight) transferBufferSize += range.Count() * sizeof(FVector4);
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.DrawIndex) transferBufferSize += range.Count() * sizeof(uint32_t);
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.Vertex.GetRanges()) transferBufferSize += range.Count() * sizeof(FFlatVertex);
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.UniformIndexes.GetRanges()) transferBufferSize += range.Count() * sizeof(int);
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.Index.GetRanges()) transferBufferSize += range.Count() * sizeof(uint32_t);
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.SurfaceIndex.GetRanges()) transferBufferSize += range.Count() * sizeof(int);
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.Surface.GetRanges()) transferBufferSize += range.Count() * sizeof(SurfaceInfo);
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.Uniforms.GetRanges()) transferBufferSize += range.Count() * sizeof(SurfaceUniforms);
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.LightUniforms.GetRanges()) transferBufferSize += range.Count() * sizeof(SurfaceLightUniforms);
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.Portals.GetRanges()) transferBufferSize += range.Count() * sizeof(PortalInfo);
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.LightIndex.GetRanges()) transferBufferSize += range.Count() * sizeof(int32_t);
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.Light.GetRanges()) transferBufferSize += range.Count() * sizeof(LightInfo);
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.DynLight.GetRanges()) transferBufferSize += range.Count() * sizeof(FVector4);
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.DrawIndex.GetRanges()) transferBufferSize += range.Count() * sizeof(uint32_t);
return transferBufferSize;
}

View file

@ -192,7 +192,7 @@ private:
void UploadLights();
template<typename T>
void UploadRanges(const TArray<MeshBufferRange>& ranges, const T* srcbuffer, VulkanBuffer* destbuffer);
void UploadRanges(const MeshBufferUploads& ranges, const T* srcbuffer, VulkanBuffer* destbuffer);
VkLevelMesh* Mesh = nullptr;
uint8_t* data = nullptr;

View file

@ -1013,7 +1013,7 @@ void VkRenderState::DrawLevelMesh(LevelMeshDrawType drawType, bool noFragmentSha
ApplyLevelMeshPipeline(mCommandBuffer, key, drawType, noFragmentShader);
for (MeshBufferRange& range : it.second)
for (const MeshBufferRange& range : it.second.GetRanges())
{
mCommandBuffer->drawIndexed(range.End - range.Start, 1, range.Start, 0, 0);
}

View file

@ -71,14 +71,8 @@ ADD_STAT(lightmap)
uint32_t atlasPixelCount = levelMesh->AtlasPixelCount();
auto stats = levelMesh->GatherTilePixelStats();
int indexBufferTotal = levelMesh->FreeLists.Index.back().End;
int indexBufferUsed = 0;
int pos = 0;
for (const auto& range : levelMesh->FreeLists.Index)
{
indexBufferUsed += range.Start - pos;
pos = range.End;
}
int indexBufferTotal = levelMesh->FreeLists.Index.GetTotalSize();
int indexBufferUsed = levelMesh->FreeLists.Index.GetUsedSize();
out.Format(
"Surfaces: %u (awaiting updates: %u)\n"
@ -403,7 +397,7 @@ void DoomLevelMesh::UploadDynLights(FLevelLocals& doomMap)
memcpy(&copyptr[4 + 4 * size0], &lightdata.arrays[1][0], size1 * sizeof(FVector4));
memcpy(&copyptr[4 + 4 * (size0 + size1)], &lightdata.arrays[2][0], size2 * sizeof(FVector4));
AddRange(UploadRanges.DynLight, { 0, totalsize });
UploadRanges.DynLight.Add(0, totalsize);
}
void DoomLevelMesh::UpdateWallPortals()
@ -466,7 +460,7 @@ void DoomLevelMesh::UpdateLight(FDynamicLight* light)
int lightindex = light->levelmesh[index].index - 1;
int portalgroup = light->levelmesh[index].portalgroup;
CopyToMeshLight(light, Mesh.Lights[lightindex], portalgroup);
AddRange(UploadRanges.Light, { lightindex, lightindex + 1 });
UploadRanges.Light.Add(lightindex, 1);
}
}
@ -902,7 +896,7 @@ void DoomLevelMesh::SetSideLights(FLevelLocals& doomMap, unsigned int sideIndex)
SetColor(uinfo.LightUniforms[i], &doomMap, lightmode, lightlevel, rel, fullbrightScene, Colormap, absalpha);
}
AddRange(UploadRanges.LightUniforms, { uinfo.Start, uinfo.Start + uinfo.Count });
UploadRanges.LightUniforms.Add(uinfo.Start, uinfo.Count);
}
}
@ -928,7 +922,7 @@ void DoomLevelMesh::SetFlatLights(FLevelLocals& doomMap, unsigned int sectorInde
{
SetColor(uinfo.LightUniforms[i], &doomMap, lightmode, lightlevel, rel, fullbrightScene, Colormap, alpha);
}
AddRange(UploadRanges.LightUniforms, { uinfo.Start, uinfo.Start + uinfo.Count });
UploadRanges.LightUniforms.Add(uinfo.Start, uinfo.Count);
}
}
@ -1115,7 +1109,7 @@ void DoomLevelMesh::AddToDrawList(TArray<DrawRangeInfo>& drawRanges, int pipelin
{
// Remember the location if we have to remove it again
DrawRangeInfo info;
info.DrawIndexStart = RemoveRange(FreeLists.DrawIndex, indexCount);
info.DrawIndexStart = FreeLists.DrawIndex.Alloc(indexCount);
info.DrawIndexCount = indexCount;
info.DrawType = drawType;
info.PipelineID = pipelineID;
@ -1123,21 +1117,18 @@ void DoomLevelMesh::AddToDrawList(TArray<DrawRangeInfo>& drawRanges, int pipelin
// Copy the indexes over from the unsorted index list
memcpy(&Mesh.DrawIndexes[info.DrawIndexStart], &Mesh.Indexes[indexStart], indexCount * sizeof(uint32_t));
AddRange(UploadRanges.DrawIndex, { info.DrawIndexStart, info.DrawIndexStart + indexCount });
UploadRanges.DrawIndex.Add(info.DrawIndexStart, indexCount);
// Add to the draw lists
AddRange(DrawList[(int)drawType][pipelineID], { info.DrawIndexStart, info.DrawIndexStart + indexCount });
DrawList[(int)drawType][pipelineID].Add(info.DrawIndexStart, indexCount);
}
void DoomLevelMesh::RemoveFromDrawList(const TArray<DrawRangeInfo>& drawRanges)
{
for (const DrawRangeInfo& info : drawRanges)
{
int start = info.DrawIndexStart;
int end = info.DrawIndexStart + info.DrawIndexCount;
RemoveRange(DrawList[(int)info.DrawType][info.PipelineID], { start, end });
AddRange(FreeLists.DrawIndex, { start, end });
DrawList[(int)info.DrawType][info.PipelineID].Remove(info.DrawIndexStart, info.DrawIndexCount);
FreeLists.DrawIndex.Free(info.DrawIndexStart, info.DrawIndexCount);
}
}
@ -1182,7 +1173,7 @@ void DoomLevelMesh::SortDrawLists()
range->DrawIndexStart = sortedStart;
}
int listEnd = indexes.Size();
list.Push({ listStart, listEnd });
list.Add(listStart, listEnd - listStart);
}
}