diff --git a/src/common/rendering/hwrenderer/data/hw_levelmesh.cpp b/src/common/rendering/hwrenderer/data/hw_levelmesh.cpp index 1477bdb46..8ef4a863e 100644 --- a/src/common/rendering/hwrenderer/data/hw_levelmesh.cpp +++ b/src/common/rendering/hwrenderer/data/hw_levelmesh.cpp @@ -46,13 +46,10 @@ void LevelMesh::Reset(const LevelMeshLimits& limits) Mesh.Indexes.Resize(limits.MaxIndexes); Mesh.SurfaceIndexes.Resize(limits.MaxIndexes / 3 + 1); - Mesh.DrawIndexes.Resize(limits.MaxIndexes); - 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); } diff --git a/src/common/rendering/hwrenderer/data/hw_levelmesh.h b/src/common/rendering/hwrenderer/data/hw_levelmesh.h index 98b354241..f819c48fd 100644 --- a/src/common/rendering/hwrenderer/data/hw_levelmesh.h +++ b/src/common/rendering/hwrenderer/data/hw_levelmesh.h @@ -180,9 +180,6 @@ public: TArray SurfaceIndexes; int IndexCount = 0; // Index range filled with data - // Indexes sorted by pipeline - TArray DrawIndexes; - // Acceleration structure nodes for when the GPU doesn't support rayquery TArray Nodes; int RootNode = 0; @@ -203,7 +200,6 @@ public: MeshBufferUploads Light; MeshBufferUploads LightIndex; MeshBufferUploads DynLight; - MeshBufferUploads DrawIndex; } UploadRanges; // Ranges in mesh currently not in use @@ -215,15 +211,11 @@ public: 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]; - // Lightmap tiles and their locations in the texture atlas struct { diff --git a/src/common/rendering/hwrenderer/data/hw_renderstate.h b/src/common/rendering/hwrenderer/data/hw_renderstate.h index adf2f3e92..d325ff73d 100644 --- a/src/common/rendering/hwrenderer/data/hw_renderstate.h +++ b/src/common/rendering/hwrenderer/data/hw_renderstate.h @@ -827,8 +827,8 @@ public: } // Draw level mesh + virtual void DrawLevelMeshRange(int firstIndex, int indexCount, int pipelineID, LevelMeshDrawType drawType, bool noFragmentShader) {} virtual void DispatchLightTiles(const VSMatrix& worldToView, float m5) { } - virtual void DrawLevelMesh(LevelMeshDrawType drawType, bool noFragmentShader) { } virtual int GetNextQueryIndex() { return 0; } virtual void BeginQuery() { } virtual void EndQuery() { } diff --git a/src/common/rendering/vulkan/vk_levelmesh.cpp b/src/common/rendering/vulkan/vk_levelmesh.cpp index ecd5ed244..771f66841 100644 --- a/src/common/rendering/vulkan/vk_levelmesh.cpp +++ b/src/common/rendering/vulkan/vk_levelmesh.cpp @@ -58,7 +58,6 @@ void VkLevelMesh::Reset() deletelist->Add(std::move(PortalBuffer)); deletelist->Add(std::move(LightBuffer)); deletelist->Add(std::move(LightIndexBuffer)); - deletelist->Add(std::move(DrawIndexBuffer)); for (BLAS& blas : DynamicBLAS) { deletelist->Add(std::move(blas.ScratchBuffer)); @@ -257,12 +256,6 @@ void VkLevelMesh::CreateBuffers() .DebugName("IndexBuffer") .Create(fb->GetDevice()); - DrawIndexBuffer = BufferBuilder() - .Usage(VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT) - .Size((size_t)Mesh->Mesh.DrawIndexes.Size() * sizeof(uint32_t)) - .DebugName("DrawIndexBuffer") - .Create(fb->GetDevice()); - NodeBuffer = BufferBuilder() .Usage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT) .Size(sizeof(CollisionNodeBufferHeader) + Mesh->Mesh.Nodes.Size() * sizeof(CollisionNode)) @@ -704,7 +697,6 @@ void VkLevelMeshUploader::Upload() UploadRanges(Mesh->Mesh->UploadRanges.Index, Mesh->Mesh->Mesh.Indexes.Data(), Mesh->IndexBuffer.get(), "IndexBuffer"); UploadRanges(Mesh->Mesh->UploadRanges.SurfaceIndex, Mesh->Mesh->Mesh.SurfaceIndexes.Data(), Mesh->SurfaceIndexBuffer.get(), "SurfaceIndexBuffer"); UploadRanges(Mesh->Mesh->UploadRanges.LightIndex, Mesh->Mesh->Mesh.LightIndexes.Data(), Mesh->LightIndexBuffer.get(), "LightIndexBuffer"); - UploadRanges(Mesh->Mesh->UploadRanges.DrawIndex, Mesh->Mesh->Mesh.DrawIndexes.Data(), Mesh->DrawIndexBuffer.get(), "DrawIndexBuffer"); UploadRanges(Mesh->Mesh->UploadRanges.LightUniforms, Mesh->Mesh->Mesh.LightUniforms.Data(), Mesh->LightUniformsBuffer.get(), "LightUniformsBuffer"); UploadRanges(Mesh->Mesh->UploadRanges.DynLight, Mesh->Mesh->Mesh.DynLights.Data(), Mesh->DynLightBuffer.get(), "DynLightBuffer"); UploadSurfaces(); @@ -746,7 +738,6 @@ void VkLevelMeshUploader::ClearRanges() 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) @@ -948,6 +939,5 @@ size_t VkLevelMeshUploader::GetTransferSize() 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(); - 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 7b362e322..f036095f4 100644 --- a/src/common/rendering/vulkan/vk_levelmesh.h +++ b/src/common/rendering/vulkan/vk_levelmesh.h @@ -89,7 +89,6 @@ public: VulkanBuffer* GetPortalBuffer() { return PortalBuffer.get(); } VulkanBuffer* GetLightBuffer() { return LightBuffer.get(); } VulkanBuffer* GetLightIndexBuffer() { return LightIndexBuffer.get(); } - VulkanBuffer* GetDrawIndexBuffer() { return DrawIndexBuffer.get(); } LevelMesh* GetMesh() { return Mesh; } @@ -138,7 +137,6 @@ private: std::unique_ptr LightBuffer; std::unique_ptr LightIndexBuffer; std::unique_ptr DynLightBuffer; - std::unique_ptr DrawIndexBuffer; std::unique_ptr NodeBuffer; diff --git a/src/common/rendering/vulkan/vk_renderstate.cpp b/src/common/rendering/vulkan/vk_renderstate.cpp index cd08a2af9..858aadf65 100644 --- a/src/common/rendering/vulkan/vk_renderstate.cpp +++ b/src/common/rendering/vulkan/vk_renderstate.cpp @@ -923,7 +923,7 @@ void VkRenderState::ApplyLevelMesh() VkBuffer vertexBuffers[2] = { fb->GetLevelMesh()->GetVertexBuffer()->buffer, fb->GetLevelMesh()->GetUniformIndexBuffer()->buffer }; VkDeviceSize vertexBufferOffsets[] = { 0, 0 }; mCommandBuffer->bindVertexBuffers(0, 2, vertexBuffers, vertexBufferOffsets); - mCommandBuffer->bindIndexBuffer(fb->GetLevelMesh()->GetDrawIndexBuffer()->buffer, 0, VK_INDEX_TYPE_UINT32); + mCommandBuffer->bindIndexBuffer(fb->GetLevelMesh()->GetIndexBuffer()->buffer, 0, VK_INDEX_TYPE_UINT32); } void VkRenderState::RunZMinMaxPass() @@ -1055,23 +1055,14 @@ void VkRenderState::DispatchLightTiles(const VSMatrix& worldToView, float m5) fb->GetCommands()->PopGroup(cmdbuffer); } -void VkRenderState::DrawLevelMesh(LevelMeshDrawType drawType, bool noFragmentShader) +void VkRenderState::DrawLevelMeshRange(int firstIndex, int indexCount, int pipelineID, LevelMeshDrawType drawType, bool noFragmentShader) { ApplyLevelMesh(); - auto mesh = fb->GetLevelMesh()->GetMesh(); - for (auto& it : mesh->DrawList[(int)drawType]) - { - int pipelineID = it.first; - const VkPipelineKey& key = fb->GetLevelMeshPipelineKey(pipelineID); + const VkPipelineKey& key = fb->GetLevelMeshPipelineKey(pipelineID); + ApplyLevelMeshPipeline(mCommandBuffer, key, drawType, noFragmentShader); - ApplyLevelMeshPipeline(mCommandBuffer, key, drawType, noFragmentShader); - - for (const MeshBufferRange& range : it.second.GetRanges()) - { - mCommandBuffer->drawIndexed(range.End - range.Start, 1, range.Start, 0, 0); - } - } + mCommandBuffer->drawIndexed(indexCount, 1, firstIndex, 0, 0); } void VkRenderState::BeginQuery() diff --git a/src/common/rendering/vulkan/vk_renderstate.h b/src/common/rendering/vulkan/vk_renderstate.h index 4bee19175..6d7ad5b55 100644 --- a/src/common/rendering/vulkan/vk_renderstate.h +++ b/src/common/rendering/vulkan/vk_renderstate.h @@ -57,8 +57,8 @@ public: void ResetVertices() override; // Draw level mesh + void DrawLevelMeshRange(int firstIndex, int indexCount, int pipelineID, LevelMeshDrawType drawType, bool noFragmentShader) override; void DispatchLightTiles(const VSMatrix& worldToView, float m5) override; - void DrawLevelMesh(LevelMeshDrawType drawType, bool noFragmentShader) override; int GetNextQueryIndex() override; void BeginQuery() override; void EndQuery() override; diff --git a/src/rendering/hwrenderer/doom_levelmesh.cpp b/src/rendering/hwrenderer/doom_levelmesh.cpp index 58604bd49..d54611dd5 100644 --- a/src/rendering/hwrenderer/doom_levelmesh.cpp +++ b/src/rendering/hwrenderer/doom_levelmesh.cpp @@ -248,7 +248,6 @@ DoomLevelMesh::DoomLevelMesh(FLevelLocals& doomMap) CreateCollision(); UploadPortals(); - SortDrawLists(); r_viewpoint.extralight = oldextralight; r_viewpoint.camera = oldcamera; @@ -319,6 +318,28 @@ void DoomLevelMesh::SetLimits(FLevelLocals& doomMap) Reset(limits); } +void DoomLevelMesh::DrawSector(FRenderState& renderstate, int sectorIndex, LevelMeshDrawType drawType, bool noFragmentShader) +{ + for (const DrawRangeInfo& di : Flats[sectorIndex].DrawRanges) + { + if (di.DrawType == drawType) + { + renderstate.DrawLevelMeshRange(di.IndexStart, di.IndexCount, di.PipelineID, drawType, noFragmentShader); + } + } +} + +void DoomLevelMesh::DrawSide(FRenderState& renderstate, int sideIndex, LevelMeshDrawType drawType, bool noFragmentShader) +{ + for (const DrawRangeInfo& di : Sides[sideIndex].DrawRanges) + { + if (di.DrawType == drawType) + { + renderstate.DrawLevelMeshRange(di.IndexStart, di.IndexCount, di.PipelineID, drawType, noFragmentShader); + } + } +} + void DoomLevelMesh::BeginFrame(FLevelLocals& doomMap) { LastFrameStats = CurFrameStats; @@ -640,7 +661,6 @@ void DoomLevelMesh::FreeSide(FLevelLocals& doomMap, unsigned int sideIndex) FreeGeometry(geo.VertexStart, geo.VertexCount, geo.IndexStart, geo.IndexCount); Sides[sideIndex].Geometries.Clear(); - RemoveFromDrawList(Sides[sideIndex].DrawRanges); Sides[sideIndex].DrawRanges.Clear(); for (auto& uni : Sides[sideIndex].Uniforms) @@ -683,7 +703,6 @@ void DoomLevelMesh::FreeFlat(FLevelLocals& doomMap, unsigned int sectorIndex) FreeGeometry(geo.VertexStart, geo.VertexCount, geo.IndexStart, geo.IndexCount); Flats[sectorIndex].Geometries.Clear(); - RemoveFromDrawList(Flats[sectorIndex].DrawRanges); Flats[sectorIndex].DrawRanges.Clear(); for (auto& uni : Flats[sectorIndex].Uniforms) @@ -1372,77 +1391,12 @@ void DoomLevelMesh::CreateWallSurface(side_t* side, HWWallDispatcher& disp, Mesh void DoomLevelMesh::AddToDrawList(TArray& drawRanges, int pipelineID, int indexStart, int indexCount, LevelMeshDrawType drawType) { - // Remember the location if we have to remove it again DrawRangeInfo info; - info.DrawIndexStart = FreeLists.DrawIndex.Alloc(indexCount); - info.DrawIndexCount = indexCount; + info.IndexStart = indexStart; + info.IndexCount = indexCount; info.DrawType = drawType; info.PipelineID = pipelineID; drawRanges.Push(info); - - // Copy the indexes over from the unsorted index list - memcpy(&Mesh.DrawIndexes[info.DrawIndexStart], &Mesh.Indexes[indexStart], indexCount * sizeof(uint32_t)); - UploadRanges.DrawIndex.Add(info.DrawIndexStart, indexCount); - - // Add to the draw lists - DrawList[(int)drawType][pipelineID].Add(info.DrawIndexStart, indexCount); -} - -void DoomLevelMesh::RemoveFromDrawList(const TArray& drawRanges) -{ - for (const DrawRangeInfo& info : drawRanges) - { - DrawList[(int)info.DrawType][info.PipelineID].Remove(info.DrawIndexStart, info.DrawIndexCount); - FreeLists.DrawIndex.Free(info.DrawIndexStart, info.DrawIndexCount); - } -} - -void DoomLevelMesh::SortDrawLists() -{ - std::unordered_map> sortedDrawList[(int)LevelMeshDrawType::NumDrawTypes]; - - for (auto& side : Sides) - { - for (auto& range : side.DrawRanges) - { - sortedDrawList[(int)range.DrawType][range.PipelineID].Push(&range); - } - } - - for (auto& flat : Flats) - { - for (auto& range : flat.DrawRanges) - { - sortedDrawList[(int)range.DrawType][range.PipelineID].Push(&range); - } - } - - TArray indexes; - - for (int drawType = 0; drawType < (int)LevelMeshDrawType::NumDrawTypes; drawType++) - { - DrawList[drawType].clear(); - for (auto& it : sortedDrawList[drawType]) - { - auto& list = DrawList[drawType][it.first]; - int listStart = indexes.Size(); - for (DrawRangeInfo* range : it.second) - { - int sortedStart = indexes.Size(); - int start = range->DrawIndexStart; - int count = range->DrawIndexCount; - for (int i = 0; i < count; i++) - { - indexes.Push(Mesh.DrawIndexes[start + i]); - } - range->DrawIndexStart = sortedStart; - } - int listEnd = indexes.Size(); - list.Add(listStart, listEnd - listStart); - } - } - - memcpy(Mesh.DrawIndexes.Data(), indexes.Data(), indexes.Size() * sizeof(uint32_t)); } int DoomLevelMesh::AddSurfaceToTile(const DoomSurfaceInfo& info, const LevelMeshSurface& surf, uint16_t sampleDimension, uint8_t alwaysUpdate) diff --git a/src/rendering/hwrenderer/doom_levelmesh.h b/src/rendering/hwrenderer/doom_levelmesh.h index b923f41b9..71f23836c 100644 --- a/src/rendering/hwrenderer/doom_levelmesh.h +++ b/src/rendering/hwrenderer/doom_levelmesh.h @@ -54,8 +54,8 @@ struct DrawRangeInfo { int PipelineID = 0; LevelMeshDrawType DrawType = {}; - int DrawIndexStart = 0; - int DrawIndexCount = 0; + int IndexStart = 0; + int IndexCount = 0; }; enum SurfaceUpdateType @@ -107,6 +107,9 @@ public: void ProcessDecals(HWDrawInfo* drawinfo, FRenderState& state); + void DrawSector(FRenderState& renderstate, int sectorIndex, LevelMeshDrawType drawType, bool noFragmentShader); + void DrawSide(FRenderState& renderstate, int sideIndex, LevelMeshDrawType drawType, bool noFragmentShader); + TArray SideDecals; TArray SidePortals; TArray WallPortals; @@ -197,8 +200,6 @@ private: void CopyToMeshLight(FDynamicLight* light, LevelMeshLight& meshlight, int portalgroup); void AddToDrawList(TArray& drawRanges, int pipelineID, int indexStart, int indexCount, LevelMeshDrawType drawType); - void RemoveFromDrawList(const TArray& drawRanges); - void SortDrawLists(); void UploadDynLights(FLevelLocals& doomMap); diff --git a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp index 3294f96b6..f71db35f9 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp @@ -477,12 +477,29 @@ void HWDrawInfo::CreateScene(bool drawpsprites, FRenderState& state) // draw level into depth buffer state.SetColorMask(false); state.SetCulling(Cull_CW); - state.DrawLevelMesh(LevelMeshDrawType::Opaque, true); - state.DrawLevelMesh(LevelMeshDrawType::Masked, true); + + int numSectors = level.sectors.Size(); + int numSides = level.sides.Size(); + + for (int i = 0; i < numSectors; i++) + level.levelMesh->DrawSector(state, i, LevelMeshDrawType::Opaque, true); + for (int i = 0; i < numSides; i++) + level.levelMesh->DrawSide(state, i, LevelMeshDrawType::Opaque, true); + + for (int i = 0; i < numSectors; i++) + level.levelMesh->DrawSector(state, i, LevelMeshDrawType::Masked, true); + for (int i = 0; i < numSides; i++) + level.levelMesh->DrawSide(state, i, LevelMeshDrawType::Masked, true); + if (gl_portals) { state.SetDepthBias(1, 128); - state.DrawLevelMesh(LevelMeshDrawType::Portal, true); + + for (int i = 0; i < numSectors; i++) + level.levelMesh->DrawSector(state, i, LevelMeshDrawType::Portal, true); + for (int i = 0; i < numSides; i++) + level.levelMesh->DrawSide(state, i, LevelMeshDrawType::Portal, true); + state.SetDepthBias(0, 0); } @@ -518,12 +535,26 @@ void HWDrawInfo::CreateScene(bool drawpsprites, FRenderState& state) state.DispatchLightTiles(VPUniforms.mViewMatrix, VPUniforms.mProjectionMatrix.get()[5]); // draw opaque level so the GPU has something to do while we examine the query results - state.DrawLevelMesh(LevelMeshDrawType::Opaque, false); - state.DrawLevelMesh(LevelMeshDrawType::Masked, false); + + for (int i = 0; i < numSectors; i++) + level.levelMesh->DrawSector(state, i, LevelMeshDrawType::Opaque, false); + for (int i = 0; i < numSides; i++) + level.levelMesh->DrawSide(state, i, LevelMeshDrawType::Opaque, false); + + for (int i = 0; i < numSectors; i++) + level.levelMesh->DrawSector(state, i, LevelMeshDrawType::Masked, false); + for (int i = 0; i < numSides; i++) + level.levelMesh->DrawSide(state, i, LevelMeshDrawType::Masked, false); + if (!gl_portals) { state.SetDepthBias(1, 128); - state.DrawLevelMesh(LevelMeshDrawType::Portal, false); + + for (int i = 0; i < numSectors; i++) + level.levelMesh->DrawSector(state, i, LevelMeshDrawType::Portal, false); + for (int i = 0; i < numSides; i++) + level.levelMesh->DrawSide(state, i, LevelMeshDrawType::Portal, false); + state.SetDepthBias(0, 0); } state.SetCulling(Cull_None);