Remove the submesh class as that caused more problems than it solved

This commit is contained in:
Magnus Norddahl 2024-01-29 21:56:42 +01:00
commit 7bc2ed5436
20 changed files with 836 additions and 994 deletions

View file

@ -7,6 +7,31 @@ LevelMesh::LevelMesh()
// Default portal
LevelMeshPortal portal;
Portals.Push(portal);
AddEmptyMesh();
UpdateCollision();
}
void LevelMesh::AddEmptyMesh()
{
// Default empty mesh (we can't make it completely empty since vulkan doesn't like that)
float minval = -100001.0f;
float maxval = -100000.0f;
Mesh.Vertices.Push({ minval, minval, minval });
Mesh.Vertices.Push({ maxval, minval, minval });
Mesh.Vertices.Push({ maxval, maxval, minval });
Mesh.Vertices.Push({ minval, minval, minval });
Mesh.Vertices.Push({ minval, maxval, minval });
Mesh.Vertices.Push({ maxval, maxval, minval });
Mesh.Vertices.Push({ minval, minval, maxval });
Mesh.Vertices.Push({ maxval, minval, maxval });
Mesh.Vertices.Push({ maxval, maxval, maxval });
Mesh.Vertices.Push({ minval, minval, maxval });
Mesh.Vertices.Push({ minval, maxval, maxval });
Mesh.Vertices.Push({ maxval, maxval, maxval });
for (int i = 0; i < 3 * 4; i++)
Mesh.Indexes.Push(i);
}
LevelMeshSurface* LevelMesh::Trace(const FVector3& start, FVector3 direction, float maxDist)
@ -21,18 +46,14 @@ LevelMeshSurface* LevelMesh::Trace(const FVector3& start, FVector3 direction, fl
{
FVector3 end = origin + direction * maxDist;
TraceHit hit0 = TriangleMeshShape::find_first_hit(StaticMesh->Collision.get(), origin, end);
TraceHit hit1 = TriangleMeshShape::find_first_hit(DynamicMesh->Collision.get(), origin, end);
LevelSubmesh* hitmesh = hit0.fraction < hit1.fraction ? StaticMesh.get() : DynamicMesh.get();
TraceHit hit = hit0.fraction < hit1.fraction ? hit0 : hit1;
TraceHit hit = TriangleMeshShape::find_first_hit(Collision.get(), origin, end);
if (hit.triangle < 0)
{
return nullptr;
}
hitSurface = hitmesh->GetSurface(hitmesh->Mesh.SurfaceIndexes[hit.triangle]);
hitSurface = GetSurface(Mesh.SurfaceIndexes[hit.triangle]);
int portal = hitSurface->PortalIndex;
if (!portal)
@ -59,44 +80,6 @@ LevelMeshSurface* LevelMesh::Trace(const FVector3& start, FVector3 direction, fl
LevelMeshTileStats LevelMesh::GatherTilePixelStats()
{
LevelMeshTileStats stats;
StaticMesh->GatherTilePixelStats(stats);
DynamicMesh->GatherTilePixelStats(stats);
return stats;
}
/////////////////////////////////////////////////////////////////////////////
LevelSubmesh::LevelSubmesh()
{
// Default empty mesh (we can't make it completely empty since vulkan doesn't like that)
float minval = -100001.0f;
float maxval = -100000.0f;
Mesh.Vertices.Push({ minval, minval, minval });
Mesh.Vertices.Push({ maxval, minval, minval });
Mesh.Vertices.Push({ maxval, maxval, minval });
Mesh.Vertices.Push({ minval, minval, minval });
Mesh.Vertices.Push({ minval, maxval, minval });
Mesh.Vertices.Push({ maxval, maxval, minval });
Mesh.Vertices.Push({ minval, minval, maxval });
Mesh.Vertices.Push({ maxval, minval, maxval });
Mesh.Vertices.Push({ maxval, maxval, maxval });
Mesh.Vertices.Push({ minval, minval, maxval });
Mesh.Vertices.Push({ minval, maxval, maxval });
Mesh.Vertices.Push({ maxval, maxval, maxval });
for (int i = 0; i < 3 * 4; i++)
Mesh.Indexes.Push(i);
UpdateCollision();
}
void LevelSubmesh::UpdateCollision()
{
Collision = std::make_unique<TriangleMeshShape>(Mesh.Vertices.Data(), Mesh.Vertices.Size(), Mesh.Indexes.Data(), Mesh.Indexes.Size());
}
void LevelSubmesh::GatherTilePixelStats(LevelMeshTileStats& stats)
{
int count = GetSurfaceCount();
for (const LightmapTile& tile : LightmapTiles)
{
@ -111,6 +94,12 @@ void LevelSubmesh::GatherTilePixelStats(LevelMeshTileStats& stats)
}
}
stats.tiles.total += LightmapTiles.Size();
return stats;
}
void LevelMesh::UpdateCollision()
{
Collision = std::make_unique<TriangleMeshShape>(Mesh.Vertices.Data(), Mesh.Vertices.Size(), Mesh.Indexes.Data(), Mesh.Indexes.Size());
}
struct LevelMeshPlaneGroup
@ -120,7 +109,7 @@ struct LevelMeshPlaneGroup
std::vector<LevelMeshSurface*> surfaces;
};
void LevelSubmesh::BuildTileSurfaceLists()
void LevelMesh::BuildTileSurfaceLists()
{
// Plane group surface is to be rendered with
TArray<LevelMeshPlaneGroup> PlaneGroups;
@ -184,12 +173,12 @@ void LevelSubmesh::BuildTileSurfaceLists()
if (surface != targetSurface && (maxUV.X < 0.0f || maxUV.Y < 0.0f || minUV.X > 1.0f || minUV.Y > 1.0f))
continue; // Bounding box not visible
tile->Surfaces.Push(surface);
tile->Surfaces.Push(GetSurfaceIndex(surface));
}
}
}
void LevelSubmesh::SetupTileTransforms()
void LevelMesh::SetupTileTransforms()
{
for (auto& tile : LightmapTiles)
{
@ -197,7 +186,7 @@ void LevelSubmesh::SetupTileTransforms()
}
}
void LevelSubmesh::PackLightmapAtlas(int lightmapStartIndex)
void LevelMesh::PackLightmapAtlas(int lightmapStartIndex)
{
std::vector<LightmapTile*> sortedTiles;
sortedTiles.reserve(LightmapTiles.Size());

View file

@ -25,24 +25,49 @@ struct LevelSubmeshDrawRange
int Count;
};
class LevelSubmesh
class LevelMesh
{
public:
LevelSubmesh();
virtual ~LevelSubmesh() = default;
LevelMesh();
virtual ~LevelMesh() = default;
virtual LevelMeshSurface* GetSurface(int index) { return nullptr; }
virtual unsigned int GetSurfaceIndex(const LevelMeshSurface* surface) const { return 0xffffffff; }
virtual int GetSurfaceCount() { return 0; }
virtual int AddSurfaceLights(const LevelMeshSurface* surface, LevelMeshLight* list, int listMaxSize) { return 0; }
LevelMeshSurface* Trace(const FVector3& start, FVector3 direction, float maxDist);
LevelMeshTileStats GatherTilePixelStats();
// Map defaults
FVector3 SunDirection = FVector3(0.0f, 0.0f, -1.0f);
FVector3 SunColor = FVector3(0.0f, 0.0f, 0.0f);
TArray<LevelMeshPortal> Portals;
struct
{
// Vertex data
TArray<FFlatVertex> Vertices;
TArray<uint32_t> Indexes;
TArray<int> SurfaceIndexes;
TArray<int> UniformIndexes;
// Surface info
TArray<SurfaceUniforms> Uniforms;
TArray<FMaterialState> Materials;
// Index data
TArray<uint32_t> Indexes;
TArray<int> SurfaceIndexes;
int DynamicIndexStart = 0;
// Above data must not be resized beyond these limits as that's the size of the GPU buffers)
int MaxVertices = 0;
int MaxIndexes = 0;
int MaxSurfaces = 0;
int MaxUniforms = 0;
int MaxSurfaceIndexes = 0;
int MaxNodes = 0;
} Mesh;
std::unique_ptr<TriangleMeshShape> Collision;
@ -62,32 +87,11 @@ public:
uint32_t AtlasPixelCount() const { return uint32_t(LMTextureCount * LMTextureSize * LMTextureSize); }
void UpdateCollision();
void GatherTilePixelStats(LevelMeshTileStats& stats);
void BuildTileSurfaceLists();
void SetupTileTransforms();
void PackLightmapAtlas(int lightmapStartIndex);
};
class LevelMesh
{
public:
LevelMesh();
virtual ~LevelMesh() = default;
std::unique_ptr<LevelSubmesh> StaticMesh = std::make_unique<LevelSubmesh>();
std::unique_ptr<LevelSubmesh> DynamicMesh = std::make_unique<LevelSubmesh>();
virtual int AddSurfaceLights(const LevelMeshSurface* surface, LevelMeshLight* list, int listMaxSize) { return 0; }
LevelMeshSurface* Trace(const FVector3& start, FVector3 direction, float maxDist);
LevelMeshTileStats GatherTilePixelStats();
// Map defaults
FVector3 SunDirection = FVector3(0.0f, 0.0f, -1.0f);
FVector3 SunColor = FVector3(0.0f, 0.0f, 0.0f);
TArray<LevelMeshPortal> Portals;
void AddEmptyMesh();
};
struct LevelMeshTileStats

View file

@ -7,14 +7,11 @@
#include "textureid.h"
#include "textures.h"
class LevelSubmesh;
class FGameTexture;
struct LevelMeshSurface;
struct LevelMeshSurface
{
LevelSubmesh* Submesh = nullptr;
struct
{
unsigned int StartVertIndex = 0;

View file

@ -45,7 +45,7 @@ struct LightmapTile
LightmapTileBinding Binding;
// Surfaces that are visible within the lightmap tile
TArray<LevelMeshSurface*> Surfaces;
TArray<int> Surfaces;
BBox Bounds;
uint16_t SampleDimension = 0;

View file

@ -92,7 +92,7 @@ void VkLevelMesh::CreateVulkanObjects()
.AddMemory(VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR | VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_SHADER_READ_BIT)
.Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR | VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR);
CreateTopLevelAS();
CreateTopLevelAS(DynamicBLAS.AccelStruct ? 2 : 1);
// Finish building the accel struct before using it from the shaders
PipelineBarrier()
@ -129,7 +129,8 @@ void VkLevelMesh::BeginFrame()
deletelist->Add(std::move(TopLevelAS.TransferBuffer));
deletelist->Add(std::move(TopLevelAS.InstanceBuffer));
DynamicBLAS = CreateBLAS(Mesh->DynamicMesh.get(), true, Mesh->StaticMesh->Mesh.Vertices.Size(), Mesh->StaticMesh->Mesh.Indexes.Size());
if (Mesh->Mesh.DynamicIndexStart < (int)Mesh->Mesh.Indexes.Size())
DynamicBLAS = CreateBLAS(true, Mesh->Mesh.DynamicIndexStart, Mesh->Mesh.Indexes.Size() - Mesh->Mesh.DynamicIndexStart);
CreateTLASInstanceBuffer();
UploadTLASInstanceBuffer();
@ -139,7 +140,7 @@ void VkLevelMesh::BeginFrame()
.AddMemory(VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR | VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_SHADER_READ_BIT)
.Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR | VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR);
UpdateTopLevelAS();
UpdateTopLevelAS(DynamicBLAS.AccelStruct ? 2 : 1);
// Finish building the accel struct before using it from the shaders
PipelineBarrier()
@ -161,36 +162,6 @@ void VkLevelMesh::UploadMeshes(bool dynamicOnly)
uploader.Upload(dynamicOnly);
}
int VkLevelMesh::GetMaxVertexBufferSize()
{
return Mesh->StaticMesh->Mesh.Vertices.Size() + MaxDynamicVertices;
}
int VkLevelMesh::GetMaxIndexBufferSize()
{
return Mesh->StaticMesh->Mesh.Indexes.Size() + MaxDynamicIndexes;
}
int VkLevelMesh::GetMaxNodeBufferSize()
{
return (int)Mesh->StaticMesh->Collision->get_nodes().size() + MaxDynamicNodes + 1; // + 1 for the merge root node
}
int VkLevelMesh::GetMaxSurfaceBufferSize()
{
return Mesh->StaticMesh->GetSurfaceCount() + MaxDynamicSurfaces;
}
int VkLevelMesh::GetMaxUniformsBufferSize()
{
return Mesh->StaticMesh->Mesh.Uniforms.Size() + MaxDynamicUniforms;
}
int VkLevelMesh::GetMaxSurfaceIndexBufferSize()
{
return Mesh->StaticMesh->Mesh.SurfaceIndexes.Size() + MaxDynamicSurfaceIndexes;
}
void VkLevelMesh::CreateBuffers()
{
VertexBuffer = BufferBuilder()
@ -201,7 +172,7 @@ void VkLevelMesh::CreateBuffers()
VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT |
VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR : 0) |
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)
.Size(GetMaxVertexBufferSize() * sizeof(FFlatVertex))
.Size(Mesh->Mesh.MaxVertices * sizeof(FFlatVertex))
.DebugName("VertexBuffer")
.Create(fb->GetDevice());
@ -209,7 +180,7 @@ void VkLevelMesh::CreateBuffers()
.Usage(
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |
VK_BUFFER_USAGE_TRANSFER_DST_BIT)
.Size(GetMaxVertexBufferSize() * sizeof(int))
.Size(Mesh->Mesh.MaxVertices * sizeof(int))
.DebugName("UniformIndexes")
.Create(fb->GetDevice());
@ -221,31 +192,31 @@ void VkLevelMesh::CreateBuffers()
VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT |
VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR : 0) |
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)
.Size((size_t)GetMaxIndexBufferSize() * sizeof(uint32_t))
.Size((size_t)Mesh->Mesh.MaxIndexes * sizeof(uint32_t))
.DebugName("IndexBuffer")
.Create(fb->GetDevice());
NodeBuffer = BufferBuilder()
.Usage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT)
.Size(sizeof(CollisionNodeBufferHeader) + GetMaxNodeBufferSize() * sizeof(CollisionNode))
.Size(sizeof(CollisionNodeBufferHeader) + Mesh->Mesh.MaxNodes * sizeof(CollisionNode))
.DebugName("NodeBuffer")
.Create(fb->GetDevice());
SurfaceIndexBuffer = BufferBuilder()
.Usage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT)
.Size(GetMaxSurfaceIndexBufferSize() * sizeof(int))
.Size(Mesh->Mesh.MaxSurfaceIndexes * sizeof(int))
.DebugName("SurfaceBuffer")
.Create(fb->GetDevice());
SurfaceBuffer = BufferBuilder()
.Usage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT)
.Size(GetMaxSurfaceBufferSize() * sizeof(SurfaceInfo))
.Size(Mesh->Mesh.MaxSurfaces * sizeof(SurfaceInfo))
.DebugName("SurfaceBuffer")
.Create(fb->GetDevice());
UniformsBuffer = BufferBuilder()
.Usage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT)
.Size(GetMaxUniformsBufferSize() * sizeof(SurfaceUniforms))
.Size(Mesh->Mesh.MaxUniforms * sizeof(SurfaceUniforms))
.DebugName("SurfaceUniformsBuffer")
.Create(fb->GetDevice());
@ -256,7 +227,7 @@ void VkLevelMesh::CreateBuffers()
.Create(fb->GetDevice());
}
VkLevelMesh::BLAS VkLevelMesh::CreateBLAS(LevelSubmesh* submesh, bool preferFastBuild, int vertexOffset, int indexOffset)
VkLevelMesh::BLAS VkLevelMesh::CreateBLAS(bool preferFastBuild, int indexOffset, int indexCount)
{
BLAS blas;
@ -272,7 +243,7 @@ VkLevelMesh::BLAS VkLevelMesh::CreateBLAS(LevelSubmesh* submesh, bool preferFast
accelStructBLDesc.geometry.triangles.vertexStride = sizeof(FFlatVertex);
accelStructBLDesc.geometry.triangles.indexType = VK_INDEX_TYPE_UINT32;
accelStructBLDesc.geometry.triangles.indexData.deviceAddress = IndexBuffer->GetDeviceAddress() + indexOffset * sizeof(uint32_t);
accelStructBLDesc.geometry.triangles.maxVertex = vertexOffset + submesh->Mesh.Vertices.Size() - 1;
accelStructBLDesc.geometry.triangles.maxVertex = Mesh->Mesh.Vertices.Size() - 1;
buildInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
buildInfo.flags = preferFastBuild ? VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR : VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR;
@ -280,7 +251,7 @@ VkLevelMesh::BLAS VkLevelMesh::CreateBLAS(LevelSubmesh* submesh, bool preferFast
buildInfo.geometryCount = 1;
buildInfo.ppGeometries = geometries;
uint32_t maxPrimitiveCount = submesh->Mesh.Indexes.Size() / 3;
uint32_t maxPrimitiveCount = indexCount / 3;
VkAccelerationStructureBuildSizesInfoKHR sizeInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR };
vkGetAccelerationStructureBuildSizesKHR(fb->GetDevice()->device, VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, &buildInfo, &maxPrimitiveCount, &sizeInfo);
@ -318,12 +289,13 @@ VkLevelMesh::BLAS VkLevelMesh::CreateBLAS(LevelSubmesh* submesh, bool preferFast
void VkLevelMesh::CreateStaticBLAS()
{
StaticBLAS = CreateBLAS(Mesh->StaticMesh.get(), false, 0, 0);
StaticBLAS = CreateBLAS(false, 0, Mesh->Mesh.DynamicIndexStart);
}
void VkLevelMesh::CreateDynamicBLAS()
{
DynamicBLAS = CreateBLAS(Mesh->DynamicMesh.get(), true, Mesh->StaticMesh->Mesh.Vertices.Size(), Mesh->StaticMesh->Mesh.Indexes.Size());
if (Mesh->Mesh.DynamicIndexStart < (int)Mesh->Mesh.Indexes.Size())
DynamicBLAS = CreateBLAS(true, Mesh->Mesh.DynamicIndexStart, Mesh->Mesh.Indexes.Size() - Mesh->Mesh.DynamicIndexStart);
}
void VkLevelMesh::CreateTLASInstanceBuffer()
@ -341,7 +313,7 @@ void VkLevelMesh::CreateTLASInstanceBuffer()
.Create(fb->GetDevice());
}
void VkLevelMesh::CreateTopLevelAS()
void VkLevelMesh::CreateTopLevelAS(int instanceCount)
{
VkAccelerationStructureBuildGeometryInfoKHR buildInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR };
VkAccelerationStructureGeometryKHR accelStructTLDesc = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR };
@ -386,12 +358,12 @@ void VkLevelMesh::CreateTopLevelAS()
VkAccelerationStructureBuildRangeInfoKHR rangeInfo = {};
VkAccelerationStructureBuildRangeInfoKHR* rangeInfos[] = { &rangeInfo };
rangeInfo.primitiveCount = 2;
rangeInfo.primitiveCount = instanceCount;
fb->GetCommands()->GetTransferCommands()->buildAccelerationStructures(1, &buildInfo, rangeInfos);
}
void VkLevelMesh::UpdateTopLevelAS()
void VkLevelMesh::UpdateTopLevelAS(int instanceCount)
{
VkAccelerationStructureBuildGeometryInfoKHR buildInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR };
VkAccelerationStructureGeometryKHR accelStructTLDesc = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR };
@ -412,7 +384,7 @@ void VkLevelMesh::UpdateTopLevelAS()
VkAccelerationStructureBuildRangeInfoKHR rangeInfo = {};
VkAccelerationStructureBuildRangeInfoKHR* rangeInfos[] = { &rangeInfo };
rangeInfo.primitiveCount = 2;
rangeInfo.primitiveCount = instanceCount;
fb->GetCommands()->GetTransferCommands()->buildAccelerationStructures(1, &buildInfo, rangeInfos);
}
@ -427,12 +399,15 @@ void VkLevelMesh::UploadTLASInstanceBuffer()
instances[0].flags = 0;
instances[0].accelerationStructureReference = StaticBLAS.AccelStruct->GetDeviceAddress();
instances[1].transform.matrix[0][0] = 1.0f;
instances[1].transform.matrix[1][1] = 1.0f;
instances[1].transform.matrix[2][2] = 1.0f;
instances[1].mask = 0xff;
instances[1].flags = 0;
instances[1].accelerationStructureReference = DynamicBLAS.AccelStruct->GetDeviceAddress();
if (DynamicBLAS.AccelStruct)
{
instances[1].transform.matrix[0][0] = 1.0f;
instances[1].transform.matrix[1][1] = 1.0f;
instances[1].transform.matrix[2][2] = 1.0f;
instances[1].mask = 0xff;
instances[1].flags = 0;
instances[1].accelerationStructureReference = DynamicBLAS.AccelStruct->GetDeviceAddress();
}
auto data = (uint8_t*)TopLevelAS.TransferBuffer->Map(0, sizeof(VkAccelerationStructureInstanceKHR) * 2);
memcpy(data, instances, sizeof(VkAccelerationStructureInstanceKHR) * 2);
@ -450,7 +425,6 @@ VkLevelMeshUploader::VkLevelMeshUploader(VkLevelMesh* mesh) : Mesh(mesh)
void VkLevelMeshUploader::Upload(bool dynamicOnly)
{
UpdateSizes();
UpdateLocations();
start = dynamicOnly;
end = locations.Size();
@ -501,6 +475,7 @@ static FVector3 SwapYZ(const FVector3& v)
void VkLevelMeshUploader::UploadNodes()
{
#if 0
// Copy node buffer header and create a root node that merges the static and dynamic AABB trees
if (locations[1].Submesh->Collision->get_root() != -1)
{
@ -530,9 +505,10 @@ void VkLevelMeshUploader::UploadNodes()
cmdbuffer->copyBuffer(transferBuffer.get(), Mesh->NodeBuffer.get(), datapos + sizeof(CollisionNodeBufferHeader), sizeof(CollisionNodeBufferHeader) + nodesHeader.root * sizeof(CollisionNode), sizeof(CollisionNode));
}
else // second submesh is empty, just point the header at the first one
#endif
{
CollisionNodeBufferHeader nodesHeader;
nodesHeader.root = locations[0].Submesh->Collision->get_root();
nodesHeader.root = Mesh->Mesh->Collision->get_root();
*((CollisionNodeBufferHeader*)(data + datapos)) = nodesHeader;
cmdbuffer->copyBuffer(transferBuffer.get(), Mesh->NodeBuffer.get(), datapos, 0, sizeof(CollisionNodeBufferHeader));
@ -543,10 +519,9 @@ void VkLevelMeshUploader::UploadNodes()
for (unsigned int i = start; i < end; i++)
{
const SubmeshBufferLocation& cur = locations[i];
auto submesh = cur.Submesh;
CollisionNode* nodes = (CollisionNode*)(data + datapos);
for (auto& node : submesh->Collision->get_nodes())
for (auto& node : Mesh->Mesh->Collision->get_nodes())
{
CollisionNode info;
info.center = SwapYZ(node.aabb.Center);
@ -557,7 +532,7 @@ void VkLevelMeshUploader::UploadNodes()
*(nodes++) = info;
}
size_t copysize = submesh->Collision->get_nodes().size() * sizeof(CollisionNode);
size_t copysize = Mesh->Mesh->Collision->get_nodes().size() * sizeof(CollisionNode);
if (copysize > 0)
cmdbuffer->copyBuffer(transferBuffer.get(), Mesh->NodeBuffer.get(), datapos, sizeof(CollisionNodeBufferHeader) + cur.Node.Offset * sizeof(CollisionNode), copysize);
datapos += copysize;
@ -569,10 +544,9 @@ void VkLevelMeshUploader::UploadVertices()
for (unsigned int i = start; i < end; i++)
{
const SubmeshBufferLocation& cur = locations[i];
auto submesh = cur.Submesh;
size_t copysize = submesh->Mesh.Vertices.Size() * sizeof(FFlatVertex);
memcpy(data + datapos, submesh->Mesh.Vertices.Data(), copysize);
size_t copysize = Mesh->Mesh->Mesh.Vertices.Size() * sizeof(FFlatVertex);
memcpy(data + datapos, Mesh->Mesh->Mesh.Vertices.Data(), copysize);
if (copysize > 0)
cmdbuffer->copyBuffer(transferBuffer.get(), Mesh->VertexBuffer.get(), datapos, cur.Vertex.Offset * sizeof(FFlatVertex), copysize);
datapos += copysize;
@ -584,10 +558,9 @@ void VkLevelMeshUploader::UploadUniformIndexes()
for (unsigned int i = start; i < end; i++)
{
const SubmeshBufferLocation& cur = locations[i];
auto submesh = cur.Submesh;
size_t copysize = submesh->Mesh.UniformIndexes.Size() * sizeof(int);
memcpy(data + datapos, submesh->Mesh.UniformIndexes.Data(), copysize);
size_t copysize = Mesh->Mesh->Mesh.UniformIndexes.Size() * sizeof(int);
memcpy(data + datapos, Mesh->Mesh->Mesh.UniformIndexes.Data(), copysize);
if (copysize > 0)
cmdbuffer->copyBuffer(transferBuffer.get(), Mesh->UniformIndexBuffer.get(), datapos, cur.UniformIndexes.Offset * sizeof(int), copysize);
datapos += copysize;
@ -599,13 +572,12 @@ void VkLevelMeshUploader::UploadIndexes()
for (unsigned int i = start; i < end; i++)
{
const SubmeshBufferLocation& cur = locations[i];
auto submesh = cur.Submesh;
uint32_t* indexes = (uint32_t*)(data + datapos);
for (int j = 0, count = submesh->Mesh.Indexes.Size(); j < count; ++j)
*(indexes++) = cur.Vertex.Offset + submesh->Mesh.Indexes[j];
for (int j = 0, count = Mesh->Mesh->Mesh.Indexes.Size(); j < count; ++j)
*(indexes++) = cur.Vertex.Offset + Mesh->Mesh->Mesh.Indexes[j];
size_t copysize = submesh->Mesh.Indexes.Size() * sizeof(uint32_t);
size_t copysize = Mesh->Mesh->Mesh.Indexes.Size() * sizeof(uint32_t);
if (copysize > 0)
cmdbuffer->copyBuffer(transferBuffer.get(), Mesh->IndexBuffer.get(), datapos, cur.Index.Offset * sizeof(uint32_t), copysize);
datapos += copysize;
@ -617,13 +589,12 @@ void VkLevelMeshUploader::UploadSurfaceIndexes()
for (unsigned int i = start; i < end; i++)
{
const SubmeshBufferLocation& cur = locations[i];
auto submesh = cur.Submesh;
int* indexes = (int*)(data + datapos);
for (int j = 0, count = submesh->Mesh.SurfaceIndexes.Size(); j < count; ++j)
*(indexes++) = cur.SurfaceIndex.Offset + submesh->Mesh.SurfaceIndexes[j];
for (int j = 0, count = Mesh->Mesh->Mesh.SurfaceIndexes.Size(); j < count; ++j)
*(indexes++) = cur.SurfaceIndex.Offset + Mesh->Mesh->Mesh.SurfaceIndexes[j];
size_t copysize = submesh->Mesh.SurfaceIndexes.Size() * sizeof(int);
size_t copysize = Mesh->Mesh->Mesh.SurfaceIndexes.Size() * sizeof(int);
if (copysize > 0)
cmdbuffer->copyBuffer(transferBuffer.get(), Mesh->SurfaceIndexBuffer.get(), datapos, cur.SurfaceIndex.Offset * sizeof(int), copysize);
datapos += copysize;
@ -635,12 +606,11 @@ void VkLevelMeshUploader::UploadSurfaces()
for (unsigned int i = start; i < end; i++)
{
const SubmeshBufferLocation& cur = locations[i];
auto submesh = cur.Submesh;
SurfaceInfo* surfaces = (SurfaceInfo*)(data + datapos);
for (int j = 0, count = submesh->GetSurfaceCount(); j < count; ++j)
for (int j = 0, count = Mesh->Mesh->GetSurfaceCount(); j < count; ++j)
{
LevelMeshSurface* surface = submesh->GetSurface(j);
LevelMeshSurface* surface = Mesh->Mesh->GetSurface(j);
SurfaceInfo info;
info.Normal = FVector3(surface->Plane.X, surface->Plane.Z, surface->Plane.Y);
@ -660,7 +630,7 @@ void VkLevelMeshUploader::UploadSurfaces()
*(surfaces++) = info;
}
size_t copysize = submesh->GetSurfaceCount() * sizeof(SurfaceInfo);
size_t copysize = Mesh->Mesh->GetSurfaceCount() * sizeof(SurfaceInfo);
if (copysize > 0)
cmdbuffer->copyBuffer(transferBuffer.get(), Mesh->SurfaceBuffer.get(), datapos, cur.Surface.Offset * sizeof(SurfaceInfo), copysize);
datapos += copysize;
@ -672,12 +642,11 @@ void VkLevelMeshUploader::UploadUniforms()
for (unsigned int i = start; i < end; i++)
{
const SubmeshBufferLocation& cur = locations[i];
auto submesh = cur.Submesh;
for (int j = 0, count = submesh->Mesh.Uniforms.Size(); j < count; j++)
for (int j = 0, count = Mesh->Mesh->Mesh.Uniforms.Size(); j < count; j++)
{
auto& surfaceUniforms = submesh->Mesh.Uniforms[j];
auto& material = submesh->Mesh.Materials[j];
auto& surfaceUniforms = Mesh->Mesh->Mesh.Uniforms[j];
auto& material = Mesh->Mesh->Mesh.Materials[j];
if (material.mMaterial)
{
auto source = material.mMaterial->Source();
@ -691,8 +660,8 @@ void VkLevelMeshUploader::UploadUniforms()
}
SurfaceUniforms* uniforms = (SurfaceUniforms*)(data + datapos);
size_t copysize = submesh->Mesh.Uniforms.Size() * sizeof(SurfaceUniforms);
memcpy(uniforms, submesh->Mesh.Uniforms.Data(), copysize);
size_t copysize = Mesh->Mesh->Mesh.Uniforms.Size() * sizeof(SurfaceUniforms);
memcpy(uniforms, Mesh->Mesh->Mesh.Uniforms.Data(), copysize);
if (copysize > 0)
cmdbuffer->copyBuffer(transferBuffer.get(), Mesh->UniformsBuffer.get(), datapos, cur.Uniforms.Offset * sizeof(SurfaceUniforms), copysize);
datapos += copysize;
@ -720,47 +689,15 @@ void VkLevelMeshUploader::UploadPortals()
void VkLevelMeshUploader::UpdateSizes()
{
for (LevelSubmesh* submesh : { Mesh->GetMesh()->StaticMesh.get(), Mesh->GetMesh()->DynamicMesh.get() })
{
SubmeshBufferLocation location;
location.Submesh = submesh;
location.Vertex.Size = submesh->Mesh.Vertices.Size();
location.Index.Size = submesh->Mesh.Indexes.Size();
location.Node.Size = (int)submesh->Collision->get_nodes().size();
location.SurfaceIndex.Size = submesh->Mesh.SurfaceIndexes.Size();
location.Surface.Size = submesh->GetSurfaceCount();
location.UniformIndexes.Size = submesh->Mesh.UniformIndexes.Size();
location.Uniforms.Size = submesh->Mesh.Uniforms.Size();
locations.Push(location);
}
}
void VkLevelMeshUploader::UpdateLocations()
{
for (unsigned int i = 1, count = locations.Size(); i < count; i++)
{
const SubmeshBufferLocation& prev = locations[i - 1];
SubmeshBufferLocation& cur = locations[i];
cur.Vertex.Offset = prev.Vertex.Offset + prev.Vertex.Size;
cur.Index.Offset = prev.Index.Offset + prev.Index.Size;
cur.Node.Offset = prev.Node.Offset + prev.Node.Size;
cur.SurfaceIndex.Offset = prev.SurfaceIndex.Offset + prev.SurfaceIndex.Size;
cur.Surface.Offset = prev.Surface.Offset + prev.Surface.Size;
cur.UniformIndexes.Offset = prev.UniformIndexes.Offset + prev.UniformIndexes.Size;
cur.Uniforms.Offset = prev.Uniforms.Offset + prev.Uniforms.Size;
if (
cur.Vertex.Offset + cur.Vertex.Size > Mesh->GetMaxVertexBufferSize() ||
cur.Index.Offset + cur.Index.Size > Mesh->GetMaxIndexBufferSize() ||
cur.Node.Offset + cur.Node.Size > Mesh->GetMaxNodeBufferSize() ||
cur.SurfaceIndex.Offset + cur.SurfaceIndex.Size > Mesh->GetMaxSurfaceIndexBufferSize() ||
cur.Surface.Offset + cur.Surface.Size > Mesh->GetMaxSurfaceBufferSize() ||
cur.UniformIndexes.Offset + cur.UniformIndexes.Size > Mesh->GetMaxVertexBufferSize() ||
cur.Uniforms.Offset + cur.Uniforms.Size > Mesh->GetMaxUniformsBufferSize())
{
I_FatalError("Dynamic accel struct buffers are too small!");
}
}
SubmeshBufferLocation location;
location.Vertex.Size = Mesh->Mesh->Mesh.Vertices.Size();
location.Index.Size = Mesh->Mesh->Mesh.Indexes.Size();
location.Node.Size = (int)Mesh->Mesh->Collision->get_nodes().size();
location.SurfaceIndex.Size = Mesh->Mesh->Mesh.SurfaceIndexes.Size();
location.Surface.Size = Mesh->Mesh->GetSurfaceCount();
location.UniformIndexes.Size = Mesh->Mesh->Mesh.UniformIndexes.Size();
location.Uniforms.Size = Mesh->Mesh->Mesh.Uniforms.Size();
locations.Push(location);
}
size_t VkLevelMeshUploader::GetTransferSize()
@ -770,13 +707,13 @@ size_t VkLevelMeshUploader::GetTransferSize()
for (unsigned int i = start; i < end; i++)
{
const SubmeshBufferLocation& cur = locations[i];
transferBufferSize += cur.Submesh->Mesh.Vertices.Size() * sizeof(FFlatVertex);
transferBufferSize += cur.Submesh->Mesh.UniformIndexes.Size() * sizeof(int);
transferBufferSize += cur.Submesh->Mesh.Indexes.Size() * sizeof(uint32_t);
transferBufferSize += cur.Submesh->Collision->get_nodes().size() * sizeof(CollisionNode);
transferBufferSize += cur.Submesh->Mesh.SurfaceIndexes.Size() * sizeof(int);
transferBufferSize += cur.Submesh->GetSurfaceCount() * sizeof(SurfaceInfo);
transferBufferSize += cur.Submesh->Mesh.Uniforms.Size() * sizeof(SurfaceUniforms);
transferBufferSize += Mesh->Mesh->Mesh.Vertices.Size() * sizeof(FFlatVertex);
transferBufferSize += Mesh->Mesh->Mesh.UniformIndexes.Size() * sizeof(int);
transferBufferSize += Mesh->Mesh->Mesh.Indexes.Size() * sizeof(uint32_t);
transferBufferSize += Mesh->Mesh->Collision->get_nodes().size() * sizeof(CollisionNode);
transferBufferSize += Mesh->Mesh->Mesh.SurfaceIndexes.Size() * sizeof(int);
transferBufferSize += Mesh->Mesh->GetSurfaceCount() * sizeof(SurfaceInfo);
transferBufferSize += Mesh->Mesh->Mesh.Uniforms.Size() * sizeof(SurfaceUniforms);
}
if (start == 0)
transferBufferSize += Mesh->GetMesh()->Portals.Size() * sizeof(PortalInfo);

View file

@ -50,7 +50,6 @@ struct SubmeshBufferRange
struct SubmeshBufferLocation
{
LevelSubmesh* Submesh = nullptr;
SubmeshBufferRange Vertex;
SubmeshBufferRange Index;
SubmeshBufferRange Node;
@ -94,20 +93,13 @@ private:
void CreateStaticBLAS();
void CreateDynamicBLAS();
void CreateTLASInstanceBuffer();
void CreateTopLevelAS();
void CreateTopLevelAS(int instanceCount);
void UploadMeshes(bool dynamicOnly);
void UploadTLASInstanceBuffer();
void UpdateTopLevelAS();
void UpdateTopLevelAS(int instanceCount);
BLAS CreateBLAS(LevelSubmesh *submesh, bool preferFastBuild, int vertexOffset, int indexOffset);
int GetMaxVertexBufferSize();
int GetMaxIndexBufferSize();
int GetMaxNodeBufferSize();
int GetMaxSurfaceBufferSize();
int GetMaxUniformsBufferSize();
int GetMaxSurfaceIndexBufferSize();
BLAS CreateBLAS(bool preferFastBuild, int indexOffset, int indexCount);
VulkanRenderDevice* fb = nullptr;
@ -168,7 +160,6 @@ private:
void UploadUniforms();
void UploadPortals();
void UpdateSizes();
void UpdateLocations();
size_t GetTransferSize();
VkLevelMesh* Mesh;

View file

@ -180,10 +180,6 @@ void VkLightmapper::Render()
viewport.height = (float)bakeImageSize;
cmdbuffer->setViewport(0, 1, &viewport);
int dynamicSurfaceIndexOffset = mesh->StaticMesh->GetSurfaceCount();
int dynamicFirstIndexOffset = mesh->StaticMesh->Mesh.Indexes.Size();
LevelSubmesh* staticMesh = mesh->StaticMesh.get();
for (int i = 0, count = selectedTiles.Size(); i < count; i++)
{
auto& selectedTile = selectedTiles[i];
@ -202,17 +198,10 @@ void VkLightmapper::Render()
bool buffersFull = false;
// Paint all surfaces visible in the tile
for (LevelMeshSurface* surface : targetTile->Surfaces)
for (int surfaceIndex : targetTile->Surfaces)
{
int surfaceIndexOffset = 0;
int firstIndexOffset = 0;
if (surface->Submesh != staticMesh)
{
surfaceIndexOffset = dynamicSurfaceIndexOffset;
firstIndexOffset = dynamicFirstIndexOffset;
}
pc.SurfaceIndex = surfaceIndexOffset + surface->Submesh->GetSurfaceIndex(surface);
LevelMeshSurface* surface = mesh->GetSurface(surfaceIndex);
pc.SurfaceIndex = surfaceIndex;
if (surface->LightList.ResetCounter != lights.ResetCounter)
{
@ -254,7 +243,7 @@ void VkLightmapper::Render()
VkDrawIndexedIndirectCommand cmd;
cmd.indexCount = surface->MeshLocation.NumElements;
cmd.instanceCount = 1;
cmd.firstIndex = firstIndexOffset + surface->MeshLocation.StartElementIndex;
cmd.firstIndex = surface->MeshLocation.StartElementIndex;
cmd.vertexOffset = 0;
cmd.firstInstance = drawindexed.Pos;
drawindexed.Constants[drawindexed.Pos] = pc;

View file

@ -483,9 +483,9 @@ void VulkanRenderDevice::BeginFrame()
levelMeshChanged = false;
mLevelMesh->SetLevelMesh(levelMesh);
if (levelMesh && levelMesh->StaticMesh->LMTextureCount > 0)
if (levelMesh && levelMesh->LMTextureCount > 0)
{
GetTextureManager()->CreateLightmap(levelMesh->StaticMesh->LMTextureSize, levelMesh->StaticMesh->LMTextureCount, std::move(levelMesh->StaticMesh->LMTextureData));
GetTextureManager()->CreateLightmap(levelMesh->LMTextureSize, levelMesh->LMTextureCount, std::move(levelMesh->LMTextureData));
GetLightmapper()->SetLevelMesh(levelMesh);
}
}

View file

@ -856,12 +856,9 @@ void VkRenderState::DrawLevelMeshSurfaces(bool noFragmentShader)
ApplyLevelMesh();
auto mesh = fb->GetLevelMesh()->GetMesh();
for (LevelSubmesh* submesh : { mesh->StaticMesh.get(), mesh->DynamicMesh.get() })
for (LevelSubmeshDrawRange& range : mesh->DrawList)
{
for (LevelSubmeshDrawRange& range : submesh->DrawList)
{
DrawLevelMeshRange(mCommandBuffer, fb->GetLevelMeshPipelineKey(range.PipelineID), range.Start, range.Count, noFragmentShader);
}
DrawLevelMeshRange(mCommandBuffer, fb->GetLevelMeshPipelineKey(range.PipelineID), range.Start, range.Count, noFragmentShader);
}
}
@ -870,12 +867,9 @@ void VkRenderState::DrawLevelMeshPortals(bool noFragmentShader)
ApplyLevelMesh();
auto mesh = fb->GetLevelMesh()->GetMesh();
for (LevelSubmesh* submesh : { mesh->StaticMesh.get(), mesh->DynamicMesh.get() })
for (LevelSubmeshDrawRange& range : mesh->PortalList)
{
for (LevelSubmeshDrawRange& range : submesh->PortalList)
{
DrawLevelMeshRange(mCommandBuffer, fb->GetLevelMeshPipelineKey(range.PipelineID), range.Start, range.Count, noFragmentShader);
}
DrawLevelMeshRange(mCommandBuffer, fb->GetLevelMeshPipelineKey(range.PipelineID), range.Start, range.Count, noFragmentShader);
}
}