Clean up the ranges code a bit
This commit is contained in:
parent
0d87875003
commit
e30831a409
7 changed files with 403 additions and 227 deletions
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(©ptr[4 + 4 * size0], &lightdata.arrays[1][0], size1 * sizeof(FVector4));
|
||||
memcpy(©ptr[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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue