Ranges in buffers are so fun!
This commit is contained in:
parent
e0cba77646
commit
766b558119
4 changed files with 116 additions and 66 deletions
|
|
@ -42,7 +42,7 @@ void LevelMesh::AddEmptyMesh()
|
|||
for (int i = 0; i < 3 * 4; i++)
|
||||
Mesh.Indexes.Push(i);
|
||||
|
||||
MarkAllDirty();
|
||||
UploadAll();
|
||||
}
|
||||
|
||||
LevelMeshSurface* LevelMesh::Trace(const FVector3& start, FVector3 direction, float maxDist)
|
||||
|
|
@ -111,7 +111,7 @@ LevelMeshTileStats LevelMesh::GatherTilePixelStats()
|
|||
void LevelMesh::UpdateCollision()
|
||||
{
|
||||
Collision = std::make_unique<TriangleMeshShape>(Mesh.Vertices.Data(), Mesh.Vertices.Size(), Mesh.Indexes.Data(), Mesh.Indexes.Size());
|
||||
MarkCollisionDirty();
|
||||
UploadCollision();
|
||||
}
|
||||
|
||||
struct LevelMeshPlaneGroup
|
||||
|
|
|
|||
|
|
@ -48,6 +48,8 @@ struct MeshBufferRange
|
|||
{
|
||||
int Offset = 0;
|
||||
int Size = 0;
|
||||
|
||||
bool operator<(const MeshBufferRange& other) const { return Offset < other.Offset; }
|
||||
};
|
||||
|
||||
class LevelMesh
|
||||
|
|
@ -83,7 +85,11 @@ public:
|
|||
info.Vertices = &Mesh.Vertices[info.VertexStart];
|
||||
info.UniformIndexes = &Mesh.UniformIndexes[info.VertexStart];
|
||||
info.Indexes = &Mesh.Indexes[info.IndexStart];
|
||||
// To do: mark range as dirty
|
||||
|
||||
AddRange(UploadRanges.Vertex, { info.VertexStart, info.VertexCount });
|
||||
AddRange(UploadRanges.UniformIndexes, { info.VertexStart, info.VertexCount });
|
||||
AddRange(UploadRanges.Index, { info.IndexStart, info.IndexCount });
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
|
|
@ -96,27 +102,33 @@ public:
|
|||
Mesh.Materials.Resize(info.Start + count);
|
||||
info.Uniforms = &Mesh.Uniforms[info.Start];
|
||||
info.Materials = &Mesh.Materials[info.Start];
|
||||
// To do: mark range as dirty
|
||||
|
||||
AddRange(UploadRanges.Uniforms, { info.Start, info.Count });
|
||||
|
||||
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;
|
||||
// To do: add to a free list
|
||||
// To do: mark range as dirty
|
||||
AddRange(UploadRanges.Index, { indexStart, indexCount });
|
||||
|
||||
AddRange(FreeLists.Vertex, { vertexStart, vertexCount });
|
||||
AddRange(FreeLists.Index, { indexStart, indexCount });
|
||||
}
|
||||
|
||||
void FreeUniforms(int start, int count)
|
||||
{
|
||||
// To do: add to a free list
|
||||
AddRange(FreeLists.Uniforms, { start, count });
|
||||
}
|
||||
|
||||
void FreeSurface(unsigned int surfaceIndex)
|
||||
{
|
||||
// To do: remove the surface from the surface tile, if attached
|
||||
// To do: add to a free list
|
||||
|
||||
AddRange(FreeLists.Surface, { (int)surfaceIndex, 1 });
|
||||
}
|
||||
|
||||
struct
|
||||
|
|
@ -161,7 +173,15 @@ public:
|
|||
TArray<MeshBufferRange> Portals;
|
||||
TArray<MeshBufferRange> Light;
|
||||
TArray<MeshBufferRange> LightIndex;
|
||||
} DirtyRanges;
|
||||
} UploadRanges;
|
||||
|
||||
struct
|
||||
{
|
||||
TArray<MeshBufferRange> Vertex;
|
||||
TArray<MeshBufferRange> Index;
|
||||
TArray<MeshBufferRange> Uniforms;
|
||||
TArray<MeshBufferRange> Surface;
|
||||
} FreeLists;
|
||||
|
||||
std::unique_ptr<TriangleMeshShape> Collision;
|
||||
|
||||
|
|
@ -186,38 +206,68 @@ public:
|
|||
|
||||
void AddEmptyMesh();
|
||||
|
||||
void MarkAllDirty()
|
||||
void UploadAll()
|
||||
{
|
||||
DirtyRanges.Vertex.Clear();
|
||||
DirtyRanges.Vertex.Push({ 0, (int)Mesh.Vertices.Size() });
|
||||
DirtyRanges.Index.Clear();
|
||||
DirtyRanges.Index.Push({ 0, (int)Mesh.Indexes.Size() });
|
||||
DirtyRanges.SurfaceIndex.Clear();
|
||||
DirtyRanges.SurfaceIndex.Push({ 0, (int)Mesh.SurfaceIndexes.Size() });
|
||||
DirtyRanges.Surface.Clear();
|
||||
DirtyRanges.Surface.Push({ 0, GetSurfaceCount() });
|
||||
DirtyRanges.UniformIndexes.Clear();
|
||||
DirtyRanges.UniformIndexes.Push({ 0, (int)Mesh.UniformIndexes.Size() });
|
||||
DirtyRanges.Uniforms.Clear();
|
||||
DirtyRanges.Uniforms.Push({ 0, (int)Mesh.Uniforms.Size() });
|
||||
DirtyRanges.Portals.Clear();
|
||||
DirtyRanges.Portals.Push({ 0, (int)Portals.Size() });
|
||||
DirtyRanges.Light.Clear();
|
||||
DirtyRanges.Light.Push({ 0, (int)Mesh.Lights.Size() });
|
||||
DirtyRanges.LightIndex.Clear();
|
||||
DirtyRanges.LightIndex.Push({ 0, (int)Mesh.LightIndexes.Size() });
|
||||
UploadRanges.Vertex.Clear();
|
||||
UploadRanges.Vertex.Push({ 0, (int)Mesh.Vertices.Size() });
|
||||
UploadRanges.Index.Clear();
|
||||
UploadRanges.Index.Push({ 0, (int)Mesh.Indexes.Size() });
|
||||
UploadRanges.SurfaceIndex.Clear();
|
||||
UploadRanges.SurfaceIndex.Push({ 0, (int)Mesh.SurfaceIndexes.Size() });
|
||||
UploadRanges.Surface.Clear();
|
||||
UploadRanges.Surface.Push({ 0, GetSurfaceCount() });
|
||||
UploadRanges.UniformIndexes.Clear();
|
||||
UploadRanges.UniformIndexes.Push({ 0, (int)Mesh.UniformIndexes.Size() });
|
||||
UploadRanges.Uniforms.Clear();
|
||||
UploadRanges.Uniforms.Push({ 0, (int)Mesh.Uniforms.Size() });
|
||||
UploadRanges.Portals.Clear();
|
||||
UploadRanges.Portals.Push({ 0, (int)Portals.Size() });
|
||||
UploadRanges.Light.Clear();
|
||||
UploadRanges.Light.Push({ 0, (int)Mesh.Lights.Size() });
|
||||
UploadRanges.LightIndex.Clear();
|
||||
UploadRanges.LightIndex.Push({ 0, (int)Mesh.LightIndexes.Size() });
|
||||
}
|
||||
|
||||
void MarkCollisionDirty()
|
||||
void UploadCollision()
|
||||
{
|
||||
DirtyRanges.Node.Clear();
|
||||
UploadRanges.Node.Clear();
|
||||
if (Collision)
|
||||
DirtyRanges.Node.Push({ 0, (int)Collision->get_nodes().size() });
|
||||
UploadRanges.Node.Push({ 0, (int)Collision->get_nodes().size() });
|
||||
}
|
||||
|
||||
void MarkDynamicDirty()
|
||||
void UploadDynamic()
|
||||
{
|
||||
DirtyRanges.Index.Push({ Mesh.DynamicIndexStart, (int)(Mesh.Indexes.Size() - Mesh.DynamicIndexStart) });
|
||||
UploadRanges.Index.Push({ Mesh.DynamicIndexStart, (int)(Mesh.Indexes.Size() - Mesh.DynamicIndexStart) });
|
||||
}
|
||||
|
||||
void AddRange(TArray<MeshBufferRange>& ranges, MeshBufferRange range)
|
||||
{
|
||||
auto right = std::lower_bound(ranges.begin(), ranges.end(), range);
|
||||
|
||||
bool leftExists = right != ranges.begin();
|
||||
bool rightExists = right != ranges.end();
|
||||
|
||||
auto left = right;
|
||||
if (leftExists)
|
||||
--left;
|
||||
|
||||
if (leftExists && rightExists && left->Offset + left->Size == range.Offset && right->Offset == range.Offset + range.Size) // ####[--]####
|
||||
{
|
||||
left->Size += range.Size + right->Size;
|
||||
ranges.Delete(right - ranges.begin());
|
||||
}
|
||||
else if (leftExists && left->Offset + left->Size == range.Offset) // ####[--] ####
|
||||
{
|
||||
left->Size += range.Size;
|
||||
}
|
||||
else if (rightExists && right->Offset == range.Offset + range.Size) // #### [--]####
|
||||
{
|
||||
right->Offset -= range.Size;
|
||||
}
|
||||
else // ##### [--] ####
|
||||
{
|
||||
ranges.Insert(right - ranges.begin(), range);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -448,11 +448,11 @@ void VkLevelMeshUploader::Upload()
|
|||
BeginTransfer(transferBufferSize);
|
||||
|
||||
UploadNodes();
|
||||
UploadRanges(Mesh->Mesh->DirtyRanges.Vertex, Mesh->Mesh->Mesh.Vertices.Data(), Mesh->VertexBuffer.get());
|
||||
UploadRanges(Mesh->Mesh->DirtyRanges.UniformIndexes, Mesh->Mesh->Mesh.UniformIndexes.Data(), Mesh->UniformIndexBuffer.get());
|
||||
UploadRanges(Mesh->Mesh->DirtyRanges.Index, Mesh->Mesh->Mesh.Indexes.Data(), Mesh->IndexBuffer.get());
|
||||
UploadRanges(Mesh->Mesh->DirtyRanges.SurfaceIndex, Mesh->Mesh->Mesh.SurfaceIndexes.Data(), Mesh->SurfaceIndexBuffer.get());
|
||||
UploadRanges(Mesh->Mesh->DirtyRanges.LightIndex, Mesh->Mesh->Mesh.LightIndexes.Data(), Mesh->LightIndexBuffer.get());
|
||||
UploadRanges(Mesh->Mesh->UploadRanges.Vertex, Mesh->Mesh->Mesh.Vertices.Data(), Mesh->VertexBuffer.get());
|
||||
UploadRanges(Mesh->Mesh->UploadRanges.UniformIndexes, Mesh->Mesh->Mesh.UniformIndexes.Data(), Mesh->UniformIndexBuffer.get());
|
||||
UploadRanges(Mesh->Mesh->UploadRanges.Index, Mesh->Mesh->Mesh.Indexes.Data(), Mesh->IndexBuffer.get());
|
||||
UploadRanges(Mesh->Mesh->UploadRanges.SurfaceIndex, Mesh->Mesh->Mesh.SurfaceIndexes.Data(), Mesh->SurfaceIndexBuffer.get());
|
||||
UploadRanges(Mesh->Mesh->UploadRanges.LightIndex, Mesh->Mesh->Mesh.LightIndexes.Data(), Mesh->LightIndexBuffer.get());
|
||||
UploadSurfaces();
|
||||
UploadUniforms();
|
||||
UploadPortals();
|
||||
|
|
@ -474,16 +474,16 @@ void VkLevelMeshUploader::Upload()
|
|||
|
||||
void VkLevelMeshUploader::ClearRanges()
|
||||
{
|
||||
Mesh->Mesh->DirtyRanges.Vertex.clear();
|
||||
Mesh->Mesh->DirtyRanges.Index.clear();
|
||||
Mesh->Mesh->DirtyRanges.Node.clear();
|
||||
Mesh->Mesh->DirtyRanges.SurfaceIndex.clear();
|
||||
Mesh->Mesh->DirtyRanges.Surface.clear();
|
||||
Mesh->Mesh->DirtyRanges.UniformIndexes.clear();
|
||||
Mesh->Mesh->DirtyRanges.Uniforms.clear();
|
||||
Mesh->Mesh->DirtyRanges.Portals.clear();
|
||||
Mesh->Mesh->DirtyRanges.Light.clear();
|
||||
Mesh->Mesh->DirtyRanges.LightIndex.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.Portals.clear();
|
||||
Mesh->Mesh->UploadRanges.Light.clear();
|
||||
Mesh->Mesh->UploadRanges.LightIndex.clear();
|
||||
}
|
||||
|
||||
void VkLevelMeshUploader::BeginTransfer(size_t transferBufferSize)
|
||||
|
|
@ -515,7 +515,7 @@ void VkLevelMeshUploader::UploadNodes()
|
|||
return;
|
||||
|
||||
// Always update the header struct of the collision storage buffer block if something changed
|
||||
if (Mesh->Mesh->DirtyRanges.Node.Size() > 0)
|
||||
if (Mesh->Mesh->UploadRanges.Node.Size() > 0)
|
||||
{
|
||||
CollisionNodeBufferHeader nodesHeader;
|
||||
nodesHeader.root = Mesh->Mesh->Collision->get_root();
|
||||
|
|
@ -527,7 +527,7 @@ void VkLevelMeshUploader::UploadNodes()
|
|||
}
|
||||
|
||||
// Copy collision nodes
|
||||
for (const MeshBufferRange& range : Mesh->Mesh->DirtyRanges.Node)
|
||||
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.Node)
|
||||
{
|
||||
const auto& srcnodes = Mesh->Mesh->Collision->get_nodes();
|
||||
CollisionNode* nodes = (CollisionNode*)(data + datapos);
|
||||
|
|
@ -565,7 +565,7 @@ void VkLevelMeshUploader::UploadRanges(const TArray<MeshBufferRange>& ranges, co
|
|||
|
||||
void VkLevelMeshUploader::UploadSurfaces()
|
||||
{
|
||||
for (const MeshBufferRange& range : Mesh->Mesh->DirtyRanges.Surface)
|
||||
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.Surface)
|
||||
{
|
||||
SurfaceInfo* surfaces = (SurfaceInfo*)(data + datapos);
|
||||
for (int j = 0, count = range.Size; j < count; j++)
|
||||
|
|
@ -601,7 +601,7 @@ void VkLevelMeshUploader::UploadSurfaces()
|
|||
|
||||
void VkLevelMeshUploader::UploadUniforms()
|
||||
{
|
||||
for (const MeshBufferRange& range : Mesh->Mesh->DirtyRanges.Uniforms)
|
||||
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.Uniforms)
|
||||
{
|
||||
for (int j = 0, count = range.Size; j < count; j++)
|
||||
{
|
||||
|
|
@ -630,7 +630,7 @@ void VkLevelMeshUploader::UploadUniforms()
|
|||
|
||||
void VkLevelMeshUploader::UploadPortals()
|
||||
{
|
||||
for (const MeshBufferRange& range : Mesh->Mesh->DirtyRanges.Portals)
|
||||
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.Portals)
|
||||
{
|
||||
PortalInfo* portals = (PortalInfo*)(data + datapos);
|
||||
for (int i = 0, count = range.Size; i < count; i++)
|
||||
|
|
@ -650,7 +650,7 @@ void VkLevelMeshUploader::UploadPortals()
|
|||
|
||||
void VkLevelMeshUploader::UploadLights()
|
||||
{
|
||||
for (const MeshBufferRange& range : Mesh->Mesh->DirtyRanges.Light)
|
||||
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.Light)
|
||||
{
|
||||
LightInfo* lights = (LightInfo*)(data + datapos);
|
||||
for (int i = 0, count = range.Size; i < count; i++)
|
||||
|
|
@ -682,17 +682,17 @@ size_t VkLevelMeshUploader::GetTransferSize()
|
|||
size_t transferBufferSize = 0;
|
||||
if (!Mesh->useRayQuery)
|
||||
{
|
||||
if (Mesh->Mesh->DirtyRanges.Node.Size() > 0) transferBufferSize += sizeof(CollisionNodeBufferHeader) + sizeof(CollisionNode);
|
||||
for (const MeshBufferRange& range : Mesh->Mesh->DirtyRanges.Node) transferBufferSize += range.Size * sizeof(CollisionNode);
|
||||
if (Mesh->Mesh->UploadRanges.Node.Size() > 0) transferBufferSize += sizeof(CollisionNodeBufferHeader) + sizeof(CollisionNode);
|
||||
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.Node) transferBufferSize += range.Size * sizeof(CollisionNode);
|
||||
}
|
||||
for (const MeshBufferRange& range : Mesh->Mesh->DirtyRanges.Vertex) transferBufferSize += range.Size * sizeof(FFlatVertex);
|
||||
for (const MeshBufferRange& range : Mesh->Mesh->DirtyRanges.UniformIndexes) transferBufferSize += range.Size * sizeof(int);
|
||||
for (const MeshBufferRange& range : Mesh->Mesh->DirtyRanges.Index) transferBufferSize += range.Size * sizeof(uint32_t);
|
||||
for (const MeshBufferRange& range : Mesh->Mesh->DirtyRanges.SurfaceIndex) transferBufferSize += range.Size * sizeof(int);
|
||||
for (const MeshBufferRange& range : Mesh->Mesh->DirtyRanges.Surface) transferBufferSize += range.Size * sizeof(SurfaceInfo);
|
||||
for (const MeshBufferRange& range : Mesh->Mesh->DirtyRanges.Uniforms) transferBufferSize += range.Size * sizeof(SurfaceUniforms);
|
||||
for (const MeshBufferRange& range : Mesh->Mesh->DirtyRanges.Portals) transferBufferSize += range.Size * sizeof(PortalInfo);
|
||||
for (const MeshBufferRange& range : Mesh->Mesh->DirtyRanges.LightIndex) transferBufferSize += range.Size * sizeof(int32_t);
|
||||
for (const MeshBufferRange& range : Mesh->Mesh->DirtyRanges.Light) transferBufferSize += range.Size * sizeof(LightInfo);
|
||||
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.Vertex) transferBufferSize += range.Size * sizeof(FFlatVertex);
|
||||
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.UniformIndexes) transferBufferSize += range.Size * sizeof(int);
|
||||
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.Index) transferBufferSize += range.Size * sizeof(uint32_t);
|
||||
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.SurfaceIndex) transferBufferSize += range.Size * sizeof(int);
|
||||
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.Surface) transferBufferSize += range.Size * sizeof(SurfaceInfo);
|
||||
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.Uniforms) transferBufferSize += range.Size * sizeof(SurfaceUniforms);
|
||||
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.Portals) transferBufferSize += range.Size * sizeof(PortalInfo);
|
||||
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.LightIndex) transferBufferSize += range.Size * sizeof(int32_t);
|
||||
for (const MeshBufferRange& range : Mesh->Mesh->UploadRanges.Light) transferBufferSize += range.Size * sizeof(LightInfo);
|
||||
return transferBufferSize;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -178,7 +178,7 @@ DoomLevelMesh::DoomLevelMesh(FLevelLocals& doomMap)
|
|||
Mesh.MaxLights = 100'000;
|
||||
Mesh.MaxLightIndexes = 4 * 1024 * 1024;
|
||||
|
||||
MarkAllDirty();
|
||||
UploadAll();
|
||||
}
|
||||
|
||||
void DoomLevelMesh::CreateLights(FLevelLocals& doomMap)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue