Change level mesh draw code to draw ranges in the mesh rather than the entire mesh
This commit is contained in:
parent
7461fc202b
commit
f302f03287
10 changed files with 73 additions and 119 deletions
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -180,9 +180,6 @@ public:
|
|||
TArray<int> SurfaceIndexes;
|
||||
int IndexCount = 0; // Index range filled with data
|
||||
|
||||
// Indexes sorted by pipeline
|
||||
TArray<uint32_t> DrawIndexes;
|
||||
|
||||
// Acceleration structure nodes for when the GPU doesn't support rayquery
|
||||
TArray<CollisionNode> 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<CPUAccelStruct> Collision;
|
||||
|
||||
// Draw index ranges for rendering the level mesh, grouped by pipeline
|
||||
std::unordered_map<int, LevelMeshDrawList> DrawList[(int)LevelMeshDrawType::NumDrawTypes];
|
||||
|
||||
// Lightmap tiles and their locations in the texture atlas
|
||||
struct
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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() { }
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<VulkanBuffer> LightBuffer;
|
||||
std::unique_ptr<VulkanBuffer> LightIndexBuffer;
|
||||
std::unique_ptr<VulkanBuffer> DynLightBuffer;
|
||||
std::unique_ptr<VulkanBuffer> DrawIndexBuffer;
|
||||
|
||||
std::unique_ptr<VulkanBuffer> NodeBuffer;
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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<DrawRangeInfo>& 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<DrawRangeInfo>& 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<int, TArray<DrawRangeInfo*>> 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<uint32_t> 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)
|
||||
|
|
|
|||
|
|
@ -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<int> SideDecals;
|
||||
TArray<int> SidePortals;
|
||||
TArray<HWWall*> WallPortals;
|
||||
|
|
@ -197,8 +200,6 @@ private:
|
|||
void CopyToMeshLight(FDynamicLight* light, LevelMeshLight& meshlight, int portalgroup);
|
||||
|
||||
void AddToDrawList(TArray<DrawRangeInfo>& drawRanges, int pipelineID, int indexStart, int indexCount, LevelMeshDrawType drawType);
|
||||
void RemoveFromDrawList(const TArray<DrawRangeInfo>& drawRanges);
|
||||
void SortDrawLists();
|
||||
|
||||
void UploadDynLights(FLevelLocals& doomMap);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue