Move inlined functions out of the class definition for better readability

This commit is contained in:
Magnus Norddahl 2024-09-07 00:42:49 +02:00
commit 5a1c8131c5
2 changed files with 215 additions and 198 deletions

View file

@ -21,6 +21,30 @@ LevelMesh::LevelMesh()
Mesh.MaxNodes = (int)std::max(Collision->get_nodes().size() * 2, (size_t)10000);
}
void LevelMesh::Reset(const LevelMeshLimits& limits)
{
Mesh.Vertices.Resize(limits.MaxVertices);
Mesh.UniformIndexes.Resize(limits.MaxVertices);
Mesh.Surfaces.Resize(limits.MaxSurfaces);
Mesh.Uniforms.Resize(limits.MaxUniforms);
Mesh.Materials.Resize(limits.MaxUniforms);
Mesh.Lights.Resize(16);
Mesh.LightIndexes.Resize(16);
Mesh.Indexes.Resize(limits.MaxIndexes);
Mesh.SurfaceIndexes.Resize(limits.MaxIndexes / 3 + 1);
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 });
}
void LevelMesh::AddEmptyMesh()
{
GeometryAllocInfo ginfo = AllocGeometry(12, 3 * 4);

View file

@ -92,98 +92,16 @@ public:
TArray<LevelMeshPortal> Portals;
GeometryAllocInfo AllocGeometry(int vertexCount, int indexCount)
{
GeometryAllocInfo info;
info.VertexStart = RemoveRange(FreeLists.Vertex, vertexCount);
info.VertexCount = vertexCount;
info.IndexStart = RemoveRange(FreeLists.Index, indexCount);
info.IndexCount = indexCount;
info.Vertices = &Mesh.Vertices[info.VertexStart];
info.UniformIndexes = &Mesh.UniformIndexes[info.VertexStart];
info.Indexes = &Mesh.Indexes[info.IndexStart];
GeometryAllocInfo AllocGeometry(int vertexCount, int indexCount);
UniformsAllocInfo AllocUniforms(int count);
SurfaceAllocInfo AllocSurface();
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 });
Mesh.IndexCount = std::max(Mesh.IndexCount, info.IndexStart + info.IndexCount);
return info;
}
UniformsAllocInfo AllocUniforms(int count)
{
UniformsAllocInfo info;
info.Start = RemoveRange(FreeLists.Uniforms, count);
info.Count = count;
info.Uniforms = &Mesh.Uniforms[info.Start];
info.Materials = &Mesh.Materials[info.Start];
AddRange(UploadRanges.Uniforms, { info.Start, info.Start + info.Count });
return info;
}
SurfaceAllocInfo AllocSurface()
{
SurfaceAllocInfo info;
info.Index = RemoveRange(FreeLists.Surface, 1);
info.Surface = &Mesh.Surfaces[info.Index];
AddRange(UploadRanges.Surface, { info.Index, info.Index + 1 });
return info;
}
void FreeGeometry(int vertexStart, int vertexCount, int indexStart, int indexCount)
{
// Convert triangles to degenerates
for (int i = 0; i < indexCount; i++)
Mesh.Indexes[indexStart + i] = 0;
AddRange(UploadRanges.Index, { indexStart, indexStart + indexCount });
AddRange(FreeLists.Vertex, { vertexStart, vertexStart + vertexCount });
AddRange(FreeLists.Index, { indexStart, indexStart + indexCount });
}
void FreeUniforms(int start, int count)
{
AddRange(FreeLists.Uniforms, { start, start + count });
}
void FreeSurface(unsigned int surfaceIndex)
{
// To do: remove the surface from the surface tile, if attached
AddRange(FreeLists.Surface, { (int)surfaceIndex, (int)surfaceIndex + 1 });
}
void FreeGeometry(int vertexStart, int vertexCount, int indexStart, int indexCount);
void FreeUniforms(int start, int count);
void FreeSurface(unsigned int surfaceIndex);
// Sets the sizes of all the GPU buffers and empties the mesh
virtual void Reset(const LevelMeshLimits& limits)
{
Mesh.Vertices.Resize(limits.MaxVertices);
Mesh.UniformIndexes.Resize(limits.MaxVertices);
Mesh.Surfaces.Resize(limits.MaxSurfaces);
Mesh.Uniforms.Resize(limits.MaxUniforms);
Mesh.Materials.Resize(limits.MaxUniforms);
Mesh.Lights.Resize(16);
Mesh.LightIndexes.Resize(16);
Mesh.Indexes.Resize(limits.MaxIndexes);
Mesh.SurfaceIndexes.Resize(limits.MaxIndexes / 3 + 1);
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 });
}
virtual void Reset(const LevelMeshLimits& limits);
// Data placed in GPU buffers
struct
@ -263,123 +181,12 @@ public:
void AddEmptyMesh();
void UploadPortals()
{
UploadRanges.Portals.Clear();
AddRange(UploadRanges.Portals, { 0, (int)Portals.Size() });
}
void UploadPortals();
void UploadCollision();
void UploadCollision()
{
UploadRanges.Node.Clear();
if (Collision)
UploadRanges.Node.Push({ 0, (int)Collision->get_nodes().size() });
}
int RemoveRange(TArray<MeshBufferRange>& ranges, int count)
{
for (unsigned int i = ranges.Size(); i > 0; i--)
{
auto& item = ranges[i - 1];
if (item.End - item.Start >= count)
{
int pos = item.Start;
item.Start += count;
if (item.Start == item.End)
{
ranges.Delete(i - 1);
}
return pos;
}
}
I_FatalError("Could not find space in level mesh buffer");
}
void 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);
}
}
void 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);
}
void AddRange(TArray<MeshBufferRange>& ranges, MeshBufferRange range);
void RemoveRange(TArray<MeshBufferRange>& ranges, MeshBufferRange range);
int RemoveRange(TArray<MeshBufferRange>& ranges, int count);
};
struct LevelMeshTileStats
@ -391,3 +198,189 @@ struct LevelMeshTileStats
Stats tiles, pixels;
};
inline GeometryAllocInfo LevelMesh::AllocGeometry(int vertexCount, int indexCount)
{
GeometryAllocInfo info;
info.VertexStart = RemoveRange(FreeLists.Vertex, vertexCount);
info.VertexCount = vertexCount;
info.IndexStart = RemoveRange(FreeLists.Index, 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 });
Mesh.IndexCount = std::max(Mesh.IndexCount, info.IndexStart + info.IndexCount);
return info;
}
inline UniformsAllocInfo LevelMesh::AllocUniforms(int count)
{
UniformsAllocInfo info;
info.Start = RemoveRange(FreeLists.Uniforms, count);
info.Count = count;
info.Uniforms = &Mesh.Uniforms[info.Start];
info.Materials = &Mesh.Materials[info.Start];
AddRange(UploadRanges.Uniforms, { info.Start, info.Start + info.Count });
return info;
}
inline SurfaceAllocInfo LevelMesh::AllocSurface()
{
SurfaceAllocInfo info;
info.Index = RemoveRange(FreeLists.Surface, 1);
info.Surface = &Mesh.Surfaces[info.Index];
AddRange(UploadRanges.Surface, { info.Index, info.Index + 1 });
return info;
}
inline void LevelMesh::FreeGeometry(int vertexStart, int vertexCount, int indexStart, int indexCount)
{
// Convert triangles to degenerates
for (int i = 0; i < indexCount; i++)
Mesh.Indexes[indexStart + i] = 0;
AddRange(UploadRanges.Index, { indexStart, indexStart + indexCount });
AddRange(FreeLists.Vertex, { vertexStart, vertexStart + vertexCount });
AddRange(FreeLists.Index, { indexStart, indexStart + indexCount });
}
inline void LevelMesh::FreeUniforms(int start, int count)
{
AddRange(FreeLists.Uniforms, { start, start + count });
}
inline void LevelMesh::FreeSurface(unsigned int surfaceIndex)
{
// To do: remove the surface from the surface tile, if attached
AddRange(FreeLists.Surface, { (int)surfaceIndex, (int)surfaceIndex + 1 });
}
inline void LevelMesh::UploadPortals()
{
UploadRanges.Portals.Clear();
AddRange(UploadRanges.Portals, { 0, (int)Portals.Size() });
}
inline void LevelMesh::UploadCollision()
{
UploadRanges.Node.Clear();
if (Collision)
UploadRanges.Node.Push({ 0, (int)Collision->get_nodes().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 = ranges.Size(); i > 0; i--)
{
auto& item = ranges[i - 1];
if (item.End - item.Start >= count)
{
int pos = item.Start;
item.Start += count;
if (item.Start == item.End)
{
ranges.Delete(i - 1);
}
return pos;
}
}
I_FatalError("Could not find space in level mesh buffer");
}