diff --git a/src/common/rendering/hwrenderer/data/hw_collision.cpp b/src/common/rendering/hwrenderer/data/hw_collision.cpp index 7c3fefc6b..13f6af43b 100644 --- a/src/common/rendering/hwrenderer/data/hw_collision.cpp +++ b/src/common/rendering/hwrenderer/data/hw_collision.cpp @@ -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 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() diff --git a/src/common/rendering/hwrenderer/data/hw_levelmesh.cpp b/src/common/rendering/hwrenderer/data/hw_levelmesh.cpp index fb8df47ef..dd7401f4f 100644 --- a/src/common/rendering/hwrenderer/data/hw_levelmesh.cpp +++ b/src/common/rendering/hwrenderer/data/hw_levelmesh.cpp @@ -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); + } +} diff --git a/src/common/rendering/hwrenderer/data/hw_levelmesh.h b/src/common/rendering/hwrenderer/data/hw_levelmesh.h index 78a3bbf5c..ab09ee1a6 100644 --- a/src/common/rendering/hwrenderer/data/hw_levelmesh.h +++ b/src/common/rendering/hwrenderer/data/hw_levelmesh.h @@ -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 Unused; +}; + +class MeshBufferUploads +{ +public: + void Clear(); + void Add(int position, int count); + const TArray& GetRanges() const { return Ranges; } + +private: + TArray Ranges; +}; + +class LevelMeshDrawList +{ +public: + void Add(int position, int count); + void Remove(int position, int count); + const TArray& GetRanges() const { return Ranges; } + +private: + TArray Ranges; +}; + struct LevelMeshLimits { int MaxVertices = 0; @@ -150,38 +188,38 @@ public: // Ranges in mesh that have changed since last upload struct { - TArray Vertex; - TArray Index; - TArray Node; - TArray SurfaceIndex; - TArray Surface; - TArray UniformIndexes; - TArray Uniforms; - TArray LightUniforms; - TArray Portals; - TArray Light; - TArray LightIndex; - TArray DynLight; - TArray 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 Vertex; - TArray Index; - TArray Uniforms; - TArray Surface; - TArray Light; - TArray LightIndex; - TArray 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 Collision; // Draw index ranges for rendering the level mesh, grouped by pipeline - std::unordered_map> DrawList[(int)LevelMeshDrawType::NumDrawTypes]; + std::unordered_map 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& ranges, MeshBufferRange range); - void RemoveRange(TArray& ranges, MeshBufferRange range); - int RemoveRange(TArray& 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& 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& 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& 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()); } diff --git a/src/common/rendering/vulkan/vk_levelmesh.cpp b/src/common/rendering/vulkan/vk_levelmesh.cpp index 468906f4a..7217f5fb4 100644 --- a/src/common/rendering/vulkan/vk_levelmesh.cpp +++ b/src/common/rendering/vulkan/vk_levelmesh.cpp @@ -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 -void VkLevelMeshUploader::UploadRanges(const TArray& 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& 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; } diff --git a/src/common/rendering/vulkan/vk_levelmesh.h b/src/common/rendering/vulkan/vk_levelmesh.h index 05e61d2ac..6b2f18b0e 100644 --- a/src/common/rendering/vulkan/vk_levelmesh.h +++ b/src/common/rendering/vulkan/vk_levelmesh.h @@ -192,7 +192,7 @@ private: void UploadLights(); template - void UploadRanges(const TArray& ranges, const T* srcbuffer, VulkanBuffer* destbuffer); + void UploadRanges(const MeshBufferUploads& ranges, const T* srcbuffer, VulkanBuffer* destbuffer); VkLevelMesh* Mesh = nullptr; uint8_t* data = nullptr; diff --git a/src/common/rendering/vulkan/vk_renderstate.cpp b/src/common/rendering/vulkan/vk_renderstate.cpp index 7ef73a5cb..5e7d9caf8 100644 --- a/src/common/rendering/vulkan/vk_renderstate.cpp +++ b/src/common/rendering/vulkan/vk_renderstate.cpp @@ -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); } diff --git a/src/rendering/hwrenderer/doom_levelmesh.cpp b/src/rendering/hwrenderer/doom_levelmesh.cpp index 148537074..d9cbf598b 100644 --- a/src/rendering/hwrenderer/doom_levelmesh.cpp +++ b/src/rendering/hwrenderer/doom_levelmesh.cpp @@ -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& 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& 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& 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); } }