Add uniforms to level mesh and upload them to the GPU

This commit is contained in:
Magnus Norddahl 2023-10-20 17:25:06 +02:00
commit ba7dfb8a8f
4 changed files with 73 additions and 1 deletions

View file

@ -231,6 +231,7 @@ public:
TArray<FFlatVertex> MeshVertices;
TArray<uint32_t> MeshElements;
TArray<int> MeshSurfaceIndexes;
TArray<SurfaceUniforms> MeshSurfaceUniforms;
TArray<LevelMeshPortal> Portals;

View file

@ -52,6 +52,7 @@ void VkRaytrace::Reset()
deletelist->Add(std::move(IndexBuffer));
deletelist->Add(std::move(NodeBuffer));
deletelist->Add(std::move(SurfaceBuffer));
deletelist->Add(std::move(SurfaceUniformsBuffer));
deletelist->Add(std::move(SurfaceIndexBuffer));
deletelist->Add(std::move(PortalBuffer));
deletelist->Add(std::move(StaticBLAS.ScratchBuffer));
@ -108,6 +109,7 @@ void VkRaytrace::UploadMeshes(bool dynamicOnly)
location.NodeSize = (int)submesh->Collision->get_nodes().size();
location.SurfaceIndexSize = submesh->MeshSurfaceIndexes.Size();
location.SurfaceSize = submesh->GetSurfaceCount();
location.SurfaceUniformsSize = submesh->MeshSurfaceUniforms.Size();
locations.Push(location);
}
@ -121,12 +123,14 @@ void VkRaytrace::UploadMeshes(bool dynamicOnly)
cur.NodeOffset = prev.NodeOffset + prev.NodeSize;
cur.SurfaceIndexOffset = prev.SurfaceIndexOffset + prev.SurfaceIndexSize;
cur.SurfaceOffset = prev.SurfaceOffset + prev.SurfaceSize;
cur.SurfaceUniformsOffset = prev.SurfaceUniformsOffset + prev.SurfaceUniformsSize;
if (
cur.VertexOffset + cur.VertexSize > GetMaxVertexBufferSize() ||
cur.IndexOffset + cur.IndexSize > GetMaxIndexBufferSize() ||
cur.NodeOffset + cur.NodeSize > GetMaxNodeBufferSize() ||
cur.SurfaceOffset + cur.SurfaceSize > GetMaxSurfaceBufferSize() ||
cur.SurfaceUniformsOffset + cur.SurfaceUniformsSize > GetMaxSurfaceUniformsBufferSize() ||
cur.SurfaceIndexOffset + cur.SurfaceIndexSize > GetMaxSurfaceIndexBufferSize())
{
I_FatalError("Dynamic accel struct buffers are too small!");
@ -146,6 +150,7 @@ void VkRaytrace::UploadMeshes(bool dynamicOnly)
transferBufferSize += cur.Submesh->Collision->get_nodes().size() * sizeof(CollisionNode);
transferBufferSize += cur.Submesh->MeshSurfaceIndexes.Size() * sizeof(int);
transferBufferSize += cur.Submesh->GetSurfaceCount() * sizeof(SurfaceInfo);
transferBufferSize += cur.Submesh->MeshSurfaceUniforms.Size() * sizeof(SurfaceUniforms);
}
if (!dynamicOnly)
transferBufferSize += Mesh->StaticMesh->Portals.Size() * sizeof(PortalInfo);
@ -284,6 +289,7 @@ void VkRaytrace::UploadMeshes(bool dynamicOnly)
info.PortalIndex = surface->portalIndex;
info.SamplingDistance = (float)surface->sampleDimension;
info.Sky = surface->bSky;
info.Alpha = surface->alpha;
if (surface->texture.isValid())
{
auto mat = FMaterial::ValidateTexture(TexMan.GetGameTexture(surface->texture), 0);
@ -293,7 +299,7 @@ void VkRaytrace::UploadMeshes(bool dynamicOnly)
{
info.TextureIndex = -1;
}
info.Alpha = surface->alpha;
submesh->MeshSurfaceUniforms[j].uTextureIndex = info.TextureIndex; // Bit of a hack, but we don't know the texture index before now
*(surfaces++) = info;
}
@ -304,6 +310,20 @@ void VkRaytrace::UploadMeshes(bool dynamicOnly)
datapos += copysize;
}
// Copy surface uniforms
for (unsigned int i = start; i < end; i++)
{
const SubmeshBufferLocation& cur = locations[i];
auto submesh = cur.Submesh;
SurfaceUniforms* uniforms = (SurfaceUniforms*)(data + datapos);
size_t copysize = submesh->MeshSurfaceUniforms.Size() * sizeof(SurfaceUniforms);
memcpy(uniforms, submesh->MeshSurfaceUniforms.Data(), copysize);
if (copysize > 0)
cmdbuffer->copyBuffer(transferBuffer.get(), SurfaceUniformsBuffer.get(), datapos, cur.SurfaceUniformsOffset * sizeof(SurfaceUniforms), copysize);
datapos += copysize;
}
// Copy portals
if (!dynamicOnly)
{
@ -353,6 +373,11 @@ int VkRaytrace::GetMaxSurfaceBufferSize()
return Mesh->StaticMesh->GetSurfaceCount() + MaxDynamicSurfaces;
}
int VkRaytrace::GetMaxSurfaceUniformsBufferSize()
{
return Mesh->StaticMesh->MeshSurfaceUniforms.Size() + MaxDynamicSurfaceUniforms;
}
int VkRaytrace::GetMaxSurfaceIndexBufferSize()
{
return Mesh->StaticMesh->MeshSurfaceIndexes.Size() + MaxDynamicSurfaceIndexes;
@ -402,6 +427,12 @@ void VkRaytrace::CreateBuffers()
.DebugName("SurfaceBuffer")
.Create(fb->GetDevice());
SurfaceUniformsBuffer = BufferBuilder()
.Usage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT)
.Size(GetMaxSurfaceUniformsBufferSize() * sizeof(SurfaceUniforms))
.DebugName("SurfaceUniformsBuffer")
.Create(fb->GetDevice());
PortalBuffer = BufferBuilder()
.Usage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT)
.Size(Mesh->StaticMesh->Portals.Size() * sizeof(PortalInfo))

View file

@ -55,6 +55,8 @@ struct SubmeshBufferLocation
int SurfaceIndexSize = 0;
int SurfaceOffset = 0;
int SurfaceSize = 0;
int SurfaceUniformsOffset = 0;
int SurfaceUniformsSize = 0;
};
class VkRaytrace
@ -71,6 +73,7 @@ public:
VulkanBuffer* GetNodeBuffer() { return NodeBuffer.get(); }
VulkanBuffer* GetSurfaceIndexBuffer() { return SurfaceIndexBuffer.get(); }
VulkanBuffer* GetSurfaceBuffer() { return SurfaceBuffer.get(); }
VulkanBuffer* GetSurfaceUniformsBuffer() { return SurfaceUniformsBuffer.get(); }
VulkanBuffer* GetPortalBuffer() { return PortalBuffer.get(); }
int GetIndexCount();
@ -99,6 +102,7 @@ private:
int GetMaxIndexBufferSize();
int GetMaxNodeBufferSize();
int GetMaxSurfaceBufferSize();
int GetMaxSurfaceUniformsBufferSize();
int GetMaxSurfaceIndexBufferSize();
VulkanRenderDevice* fb = nullptr;
@ -112,6 +116,7 @@ private:
std::unique_ptr<VulkanBuffer> IndexBuffer;
std::unique_ptr<VulkanBuffer> SurfaceIndexBuffer;
std::unique_ptr<VulkanBuffer> SurfaceBuffer;
std::unique_ptr<VulkanBuffer> SurfaceUniformsBuffer;
std::unique_ptr<VulkanBuffer> PortalBuffer;
std::unique_ptr<VulkanBuffer> NodeBuffer;
@ -120,6 +125,7 @@ private:
static const int MaxDynamicVertices = 100'000;
static const int MaxDynamicIndexes = 100'000;
static const int MaxDynamicSurfaces = 100'000;
static const int MaxDynamicSurfaceUniforms = 100'000;
static const int MaxDynamicSurfaceIndexes = 25'000;
static const int MaxDynamicNodes = 10'000;

View file

@ -665,8 +665,11 @@ void DoomLevelSubmesh::CreateLinePortalSurface(FLevelLocals& doomMap, side_t* si
surf.sectorGroup = sectorGroup[front->Index()];
surf.AlwaysUpdate = !!(front->Flags & SECF_LM_DYNAMIC);
SurfaceUniforms uniforms = {};
SetSideTextureUVs(surf, side, side_t::top, v1Top, v1Bottom, v2Top, v2Bottom);
MeshSurfaceUniforms.Push(uniforms);
Surfaces.Push(surf);
}
@ -761,8 +764,11 @@ void DoomLevelSubmesh::CreateLineHorizonSurface(FLevelLocals& doomMap, side_t* s
surf.sectorGroup = sectorGroup[front->Index()];
surf.AlwaysUpdate = !!(front->Flags & SECF_LM_DYNAMIC);
SurfaceUniforms uniforms = {};
SetSideTextureUVs(surf, side, side_t::top, v1Top, v1Bottom, v2Top, v2Bottom);
MeshSurfaceUniforms.Push(uniforms);
Surfaces.Push(surf);
}
@ -815,8 +821,12 @@ void DoomLevelSubmesh::CreateFrontWallSurface(FLevelLocals& doomMap, side_t* sid
surf.texture = side->textures[side_t::mid].texture;
surf.AlwaysUpdate = !!(front->Flags & SECF_LM_DYNAMIC);
SurfaceUniforms uniforms = {};
uniforms.uLightLevel = front->lightlevel;
SetSideTextureUVs(surf, side, side_t::top, v1Top, v1Bottom, v2Top, v2Bottom);
MeshSurfaceUniforms.Push(uniforms);
Surfaces.Push(surf);
}
@ -904,8 +914,12 @@ void DoomLevelSubmesh::CreateMidWallSurface(FLevelLocals& doomMap, side_t* side)
surf.alpha = float(side->linedef->alpha);
surf.AlwaysUpdate = !!(front->Flags & SECF_LM_DYNAMIC);
SurfaceUniforms uniforms = {};
uniforms.uLightLevel = front->lightlevel;
SetSideTextureUVs(surf, side, side_t::top, verts[2].z, verts[0].z, verts[3].z, verts[1].z);
MeshSurfaceUniforms.Push(uniforms);
Surfaces.Push(surf);
}
@ -974,8 +988,12 @@ void DoomLevelSubmesh::Create3DFloorWallSurfaces(FLevelLocals& doomMap, side_t*
surf.texture = side->textures[side_t::mid].texture;
surf.AlwaysUpdate = !!(front->Flags & SECF_LM_DYNAMIC);
SurfaceUniforms uniforms = {};
uniforms.uLightLevel = front->lightlevel;
SetSideTextureUVs(surf, side, side_t::top, tlZ, blZ, trZ, brZ);
MeshSurfaceUniforms.Push(uniforms);
Surfaces.Push(surf);
}
}
@ -1026,8 +1044,12 @@ void DoomLevelSubmesh::CreateTopWallSurface(FLevelLocals& doomMap, side_t* side)
surf.texture = side->textures[side_t::top].texture;
surf.AlwaysUpdate = !!(front->Flags & SECF_LM_DYNAMIC);
SurfaceUniforms uniforms = {};
uniforms.uLightLevel = front->lightlevel;
SetSideTextureUVs(surf, side, side_t::top, v1Top, v1TopBack, v2Top, v2TopBack);
MeshSurfaceUniforms.Push(uniforms);
Surfaces.Push(surf);
}
@ -1076,8 +1098,12 @@ void DoomLevelSubmesh::CreateBottomWallSurface(FLevelLocals& doomMap, side_t* si
surf.texture = side->textures[side_t::bottom].texture;
surf.AlwaysUpdate = !!(front->Flags & SECF_LM_DYNAMIC);
SurfaceUniforms uniforms = {};
uniforms.uLightLevel = front->lightlevel;
SetSideTextureUVs(surf, side, side_t::bottom, v1BottomBack, v1Bottom, v2BottomBack, v2Bottom);
MeshSurfaceUniforms.Push(uniforms);
Surfaces.Push(surf);
}
@ -1174,6 +1200,10 @@ void DoomLevelSubmesh::CreateFloorSurface(FLevelLocals &doomMap, subsector_t *su
surf.sectorGroup = sectorGroup[sector->Index()];
surf.AlwaysUpdate = !!(sector->Flags & SECF_LM_DYNAMIC);
SurfaceUniforms uniforms = {};
uniforms.uLightLevel = sector->lightlevel;
MeshSurfaceUniforms.Push(uniforms);
Surfaces.Push(surf);
}
@ -1229,6 +1259,10 @@ void DoomLevelSubmesh::CreateCeilingSurface(FLevelLocals& doomMap, subsector_t*
surf.sectorGroup = sectorGroup[sector->Index()];
surf.AlwaysUpdate = !!(sector->Flags & SECF_LM_DYNAMIC);
SurfaceUniforms uniforms = {};
uniforms.uLightLevel = sector->lightlevel;
MeshSurfaceUniforms.Push(uniforms);
Surfaces.Push(surf);
}